home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / c / minigl.lha / MiniGL / src / vertexelements.c < prev   
Encoding:
C/C++ Source or Header  |  2002-06-02  |  66.0 KB  |  3,178 lines

  1. //Note: tristrip backface-culling is disabled for clipping events because of an unidentified bug
  2.  
  3. #include "sysinc.h"
  4. #include "vertexarray.h"
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <math.h>
  10.  
  11.  
  12. /*
  13. ** glDrawElements pipeline by Christian 'Surgeon' Michael
  14. ** Thanks to Olivier Fabre for bug-hunting
  15. **
  16. ** major revision 05-07 april 2002:
  17. ** optimized path for GL_EXT_compiled_vertex_array
  18. **
  19. */
  20.  
  21. extern void TMA_Start(LockTimeHandle *handle);
  22. extern GLboolean TMA_Check(LockTimeHandle *handle);
  23. extern void fog_Set(GLcontext context);
  24.  
  25. void GLLockArrays(GLcontext context, GLuint first, GLsizei count);
  26. void GLUnLockArrays(GLcontext context);
  27.  
  28. extern void AE_ClipPoly(GLcontext context, PolyBuffer *out, int clipstart, ULONG or_codes);
  29.  
  30. extern void m_CombineMatrices(GLcontext context);
  31.  
  32. extern GLboolean DecideFrontface(GLcontext context, const MGLVertex *a, const MGLVertex *b, const MGLVertex *c, const int sign);
  33.  
  34. extern Convfn Convert;
  35.  
  36. GLboolean Clip_Volume_Bypass = GL_FALSE; //for compiled arrays
  37.  
  38. //NYI:
  39.  
  40. void E_DrawPoints        (GLcontext context, const int count, const UWORD *idx);
  41. void E_DrawLines         (GLcontext context, const int count, const UWORD *idx);
  42. void E_DrawLineStrip     (GLcontext context, const int count, const UWORD *idx);
  43. void E_DrawLineLoop      (GLcontext context, const int count, const UWORD *idx);
  44.  
  45. void E_DrawQuads         (GLcontext context, const int count, const UWORD *idx);
  46. void E_DrawQuadStrip     (GLcontext context, const int count, const UWORD *idx);
  47.  
  48. //implemented:
  49.  
  50.  
  51. void E_DrawTriFan       (GLcontext context, const int count, UWORD *idx);
  52.  
  53. void E_DrawPolygon       (GLcontext context, const int count, UWORD *idx);
  54.  
  55. void E_DrawTriStrip       (GLcontext context, const int count, const UWORD *idx);
  56.  
  57. void E_DrawTriangles     (GLcontext context, const int count, const UWORD *idx);
  58.  
  59. void E_DrawFlatFan       (GLcontext context, const int count, const UWORD *idx);
  60.  
  61. static PolyBuffer clip[MGL_MAXVERTS>>2];
  62. static PolyBuffer polys[MGL_MAXVERTS>>2];
  63.  
  64.  
  65. INLINE GLboolean E_CheckTri(GLcontext context, const MGLVertex *a, const MGLVertex *b, const MGLVertex *c, const int sign)
  66. {
  67.     float area;
  68.     float x1,y1;
  69.     float x2,y2;
  70.  
  71.     x1 = b->v.x - a->v.x;
  72.     y1 = b->v.y - a->v.y;
  73.     x2 = c->v.x - a->v.x;
  74.     y2 = c->v.y - a->v.y;
  75.            
  76.     area = y2*x1 - x2*y1;
  77.  
  78.     if(sign > 0)
  79.         area = -area;
  80.  
  81.     if(area < context->MinTriArea)
  82.         return GL_FALSE;
  83.     else
  84.         return GL_TRUE;
  85. }
  86.  
  87.  
  88. #define OF_11 0
  89. #define OF_12 4
  90. #define OF_13 8
  91. #define OF_14 12
  92.  
  93. #define OF_21 1
  94. #define OF_22 5
  95. #define OF_23 9
  96. #define OF_24 13
  97.  
  98. #define OF_31 2
  99. #define OF_32 6
  100. #define OF_33 10
  101. #define OF_34 14
  102.  
  103. #define OF_41 3
  104. #define OF_42 7
  105. #define OF_43 11
  106. #define OF_44 15
  107.  
  108.  
  109. void TransformIndex(GLcontext context, const int size, const UWORD *idx)
  110. {
  111.    int i;
  112.  
  113.    #define a(x) (context->CombinedMatrix.v[OF_##x])
  114.  
  115.    if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  116.    {
  117.     static int m[16];
  118.     int tx,ty,tz,tw;
  119.     int x,y,z;
  120.     int cw;
  121.       int *vp;
  122.     ULONG local_outcode;
  123.     UBYTE *vpointer;
  124.     MGLVertex *v;
  125.     int stride;
  126.     const float fix2float = 1.f/32768.f;
  127.  
  128.       #define CLIP_EPS ((int)((1e-7)*32768.f))
  129.  
  130.      #define b(x) (m[OF_##x])
  131.  
  132.       if(context->CombinedValid == GL_FALSE)
  133.     {
  134.     const float float2fix = 32768.f;
  135.  
  136.             m_CombineMatrices(context);
  137.  
  138.         b(11)=(int)(a(11)*float2fix);
  139.         b(12)=(int)(a(12)*float2fix);
  140.         b(13)=(int)(a(13)*float2fix);
  141.         b(14)=(int)(a(14)*float2fix);
  142.         b(21)=(int)(a(21)*float2fix);
  143.         b(22)=(int)(a(22)*float2fix);
  144.         b(23)=(int)(a(23)*float2fix);
  145.         b(24)=(int)(a(24)*float2fix);
  146.         b(31)=(int)(a(31)*float2fix);
  147.         b(32)=(int)(a(32)*float2fix);
  148.         b(33)=(int)(a(33)*float2fix);
  149.         b(34)=(int)(a(34)*float2fix);
  150.         b(41)=(int)(a(41)*float2fix);
  151.         b(42)=(int)(a(42)*float2fix);
  152.         b(43)=(int)(a(43)*float2fix);
  153.         b(44)=(int)(a(44)*float2fix);
  154.     }
  155.  
  156.      stride = context->ArrayPointer.vertexstride;
  157.  
  158.      i = size-1;
  159.      do
  160.      {
  161.      v = &(context->VertexBuffer[idx[i]]);
  162.      vpointer = (context->ArrayPointer.verts + idx[i]*stride);
  163.  
  164.       vp = (int *)vpointer;
  165.  
  166.       x = vp[0];
  167.       y = vp[1];
  168.       z = vp[2];
  169.  
  170.     //pipelined transformations
  171.  
  172.        tx  = x*b(11);
  173.        ty  = x*b(21);
  174.        tz  = x*b(31);
  175.        tw  = x*b(41);
  176.  
  177.     tx += y*b(12);
  178.     ty += y*b(22);
  179.     tz += y*b(32);
  180.     tw += y*b(42);
  181.  
  182.     tx += z*b(13);
  183.     ty += z*b(23);
  184.     tz += z*b(33);
  185.     tw += z*b(43);
  186.  
  187.     tx += b(14);
  188.     ty += b(24);
  189.     tz += b(34);
  190.     tw += b(44);
  191.  
  192.     local_outcode = 0;
  193.  
  194.         if (tw < CLIP_EPS )
  195.       {
  196.                 local_outcode |= MGL_CLIP_NEGW;
  197.       }        
  198.         if (-tw > tx)
  199.         {
  200.                 local_outcode |= MGL_CLIP_LEFT;
  201.         }
  202.         else if (tx > tw)
  203.         {
  204.                 local_outcode |= MGL_CLIP_RIGHT;
  205.         }
  206.  
  207.         if (-tw > ty)
  208.         {
  209.                 local_outcode |= MGL_CLIP_BOTTOM;
  210.         }
  211.         else if (ty > tw)
  212.         {
  213.                 local_outcode |= MGL_CLIP_TOP;
  214.         }
  215.         
  216.         if (-tw > tz)
  217.         {
  218.                 local_outcode |= MGL_CLIP_BACK;
  219.         }
  220.         else if (tz > tw)
  221.         {
  222.                 local_outcode |= MGL_CLIP_FRONT;
  223.         }
  224.  
  225.     v->bx = (float)tx*fix2float;    
  226.     v->by = (float)ty*fix2float;
  227.     v->bz = (float)tz*fix2float;    
  228.     v->bw = (float)tw*fix2float;    
  229.  
  230.       v->outcode = local_outcode;
  231.  
  232.      } while (i--);
  233.  
  234.     #undef b
  235.     #undef CLIP_EPS    
  236.    }
  237.    else
  238.    {
  239.       float a11,a12,a13,a14;
  240.       float a21,a22,a23,a24;
  241.       float a31,a32,a33,a34;
  242.       float a41,a42,a43,a44;
  243.       float *vp;
  244.       float cw;
  245.       float x,y,z;
  246.     ULONG local_outcode;
  247.     UBYTE *vpointer;
  248.     MGLVertex *v;
  249.     int stride;
  250.  
  251.       #define CLIP_EPS (1e-7)
  252.  
  253.      if(context->CombinedValid == GL_FALSE)
  254.             m_CombineMatrices(context);
  255.  
  256.      a11=a(11); a12=a(12); a13=a(13); a14=a(14);
  257.      a21=a(21); a22=a(22); a23=a(23); a24=a(24);
  258.      a31=a(31); a32=a(32); a33=a(33); a34=a(34);
  259.      a41=a(41); a42=a(42); a43=a(43); a44=a(44);
  260.  
  261.      stride = context->ArrayPointer.vertexstride;
  262.  
  263.      i = size-1;
  264.  
  265.      do
  266.      {
  267.      v = &(context->VertexBuffer[idx[i]]);
  268.      vpointer = (context->ArrayPointer.verts + idx[i]*stride);
  269.      vp = (float *)vpointer;
  270.  
  271.         x = vp[0];
  272.         y = vp[1];
  273.         z = vp[2];
  274.  
  275.         v->bx = a11*x + a12*y + a13*z + a14;
  276.         v->by = a21*x + a22*y + a23*z + a24;
  277.         v->bz = a31*x + a32*y + a33*z + a34;
  278.         v->bw = a41*x + a42*y + a43*z + a44;
  279.  
  280.         cw = v->bw;
  281.         local_outcode = 0;
  282.  
  283.         if (cw < CLIP_EPS )
  284.                 local_outcode |= MGL_CLIP_NEGW;
  285.         
  286.         if (-cw > v->bx)
  287.         {
  288.                 local_outcode |= MGL_CLIP_LEFT;
  289.         }
  290.         else if (v->bx > cw)
  291.         {
  292.                 local_outcode |= MGL_CLIP_RIGHT;
  293.         }
  294.  
  295.         if (-cw > v->by)
  296.         {
  297.                 local_outcode |= MGL_CLIP_BOTTOM;
  298.         }
  299.         else if (v->by > cw)
  300.         {
  301.                 local_outcode |= MGL_CLIP_TOP;
  302.         }
  303.         
  304.         if (-cw > v->bz)
  305.         {
  306.                 local_outcode |= MGL_CLIP_BACK;
  307.         }
  308.         else if (v->bz > cw)
  309.         {
  310.                 local_outcode |= MGL_CLIP_FRONT;
  311.         }
  312.  
  313.         v->outcode = local_outcode;
  314.  
  315.      } while (i--);
  316.  
  317.      #undef CLIP_EPS
  318.      #undef a
  319.    }
  320. }
  321.  
  322.  
  323. //following 5 functions are called from glLockArrays
  324. //05-04-02    returns number of onscreen verts
  325.  
  326. INLINE ULONG TransformRange(GLcontext context, const int first, const int size)
  327. {
  328.    int i;
  329.    ULONG border;
  330.  
  331.    #define a(x) (context->CombinedMatrix.v[OF_##x])
  332.  
  333.    if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  334.    {
  335.     static int m[16];
  336.     int tx,ty,tz,tw;
  337.     int x,y,z;
  338.     int cw;
  339.       int *vp;
  340.     ULONG local_outcode;
  341.     UBYTE *vpointer;
  342.     MGLVertex *v;
  343.     int stride;
  344.  
  345.       #define CLIP_EPS ((int)((1e-7)*32768.f))
  346.  
  347.      #define b(x) (m[OF_##x])
  348.  
  349.       if(context->CombinedValid == GL_FALSE)
  350.     {
  351.     const float float2fix = 32768.f;
  352.  
  353.             m_CombineMatrices(context);
  354.  
  355.         b(11)=(int)(a(11)*float2fix);
  356.         b(12)=(int)(a(12)*float2fix);
  357.         b(13)=(int)(a(13)*float2fix);
  358.         b(14)=(int)(a(14)*float2fix);
  359.         b(21)=(int)(a(21)*float2fix);
  360.         b(22)=(int)(a(22)*float2fix);
  361.         b(23)=(int)(a(23)*float2fix);
  362.         b(24)=(int)(a(24)*float2fix);
  363.         b(31)=(int)(a(31)*float2fix);
  364.         b(32)=(int)(a(32)*float2fix);
  365.         b(33)=(int)(a(33)*float2fix);
  366.         b(34)=(int)(a(34)*float2fix);
  367.         b(41)=(int)(a(41)*float2fix);
  368.         b(42)=(int)(a(42)*float2fix);
  369.         b(43)=(int)(a(43)*float2fix);
  370.         b(44)=(int)(a(44)*float2fix);
  371.     }
  372.  
  373.      stride = context->ArrayPointer.vertexstride;
  374.      vpointer = (context->ArrayPointer.verts + first*stride);
  375.  
  376.      v = &(context->VertexBuffer[first]);
  377.  
  378.      border = 0;
  379.      i = size;
  380.  
  381.      do
  382.      {
  383.  
  384.       vp = (int *)vpointer;
  385.  
  386.       x = vp[0];
  387.       y = vp[1];
  388.       z = vp[2];
  389.  
  390.     //pipelined transformations
  391.  
  392.        tx  = x*b(11);
  393.        ty  = x*b(21);
  394.        tz  = x*b(31);
  395.        tw  = x*b(41);
  396.  
  397.     tx += y*b(12);
  398.     ty += y*b(22);
  399.     tz += y*b(32);
  400.     tw += y*b(42);
  401.  
  402.     tx += z*b(13);
  403.     ty += z*b(23);
  404.     tz += z*b(33);
  405.     tw += z*b(43);
  406.  
  407.     tx += b(14);
  408.     ty += b(24);
  409.     tz += b(34);
  410.     tw += b(44);
  411.  
  412.     local_outcode = 0;
  413.  
  414.         if (tw < CLIP_EPS )
  415.       {
  416.                 local_outcode |= MGL_CLIP_NEGW;
  417.       }        
  418.         if (-tw > tx)
  419.         {
  420.                 local_outcode |= MGL_CLIP_LEFT;
  421.         }
  422.         else if (tx > tw)
  423.         {
  424.                 local_outcode |= MGL_CLIP_RIGHT;
  425.         }
  426.  
  427.         if (-tw > ty)
  428.         {
  429.                 local_outcode |= MGL_CLIP_BOTTOM;
  430.         }
  431.         else if (ty > tw)
  432.         {
  433.                 local_outcode |= MGL_CLIP_TOP;
  434.         }
  435.         
  436.         if (-tw > tz)
  437.         {
  438.                 local_outcode |= MGL_CLIP_BACK;
  439.         }
  440.         else if (tz > tw)
  441.         {
  442.                 local_outcode |= MGL_CLIP_FRONT;
  443.         }
  444.  
  445.     border |= local_outcode;
  446.  
  447.       v->outcode = local_outcode;
  448.  
  449.     v->bx = (float)tx;    
  450.     v->by = (float)ty;
  451.     v->bz = (float)tz;    
  452.     v->bw = (float)tw;    
  453.  
  454.      v++; vpointer += stride;
  455.  
  456.      } while (--i);
  457.  
  458.     #undef b
  459.     #undef CLIP_EPS    
  460.    }
  461.    else
  462.    {
  463.      float a11,a12,a13,a14;
  464.      float a21,a22,a23,a24;
  465.      float a31,a32,a33,a34;
  466.      float a41,a42,a43,a44;
  467.      float *vp;
  468.      float cw;
  469.      float x,y,z;
  470.      ULONG local_outcode;
  471.      UBYTE *vpointer;
  472.      MGLVertex *v;
  473.      int stride;
  474.  
  475.      #define CLIP_EPS (1e-7)
  476.  
  477.      if(context->CombinedValid == GL_FALSE)
  478.             m_CombineMatrices(context);
  479.  
  480.      a11=a(11); a12=a(12); a13=a(13); a14=a(14);
  481.      a21=a(21); a22=a(22); a23=a(23); a24=a(24);
  482.      a31=a(31); a32=a(32); a33=a(33); a34=a(34);
  483.      a41=a(41); a42=a(42); a43=a(43); a44=a(44);
  484.  
  485.      stride = context->ArrayPointer.vertexstride;
  486.      vpointer = (context->ArrayPointer.verts + first*stride);
  487.  
  488.      v = &(context->VertexBuffer[first]);
  489.  
  490.      i = size;
  491.  
  492.      do
  493.      {
  494.         vp = (float *)vpointer;
  495.  
  496.         x = vp[0];
  497.         y = vp[1];
  498.         z = vp[2];
  499.  
  500.         v->bx = a11*x + a12*y + a13*z + a14;
  501.         v->by = a21*x + a22*y + a23*z + a24;
  502.         v->bz = a31*x + a32*y + a33*z + a34;
  503.         v->bw = a41*x + a42*y + a43*z + a44;
  504.  
  505.      v++; vpointer += stride;
  506.  
  507.      } while (--i);
  508.  
  509.      v = &context->VertexBuffer[first];
  510.      i = size;
  511.      border = 0;
  512.  
  513.      do
  514.      {
  515.         cw = v->bw;
  516.         local_outcode = 0;
  517.  
  518.         if (cw < CLIP_EPS )
  519.       {
  520.                 local_outcode |= MGL_CLIP_NEGW;
  521.       }        
  522.         if (-cw > v->bx)
  523.         {
  524.                 local_outcode |= MGL_CLIP_LEFT;
  525.         }
  526.         else if (v->bx > cw)
  527.         {
  528.                 local_outcode |= MGL_CLIP_RIGHT;
  529.         }
  530.  
  531.         if (-cw > v->by)
  532.         {
  533.                 local_outcode |= MGL_CLIP_BOTTOM;
  534.         }
  535.         else if (v->by > cw)
  536.         {
  537.                 local_outcode |= MGL_CLIP_TOP;
  538.         }
  539.         
  540.         if (-cw > v->bz)
  541.         {
  542.                 local_outcode |= MGL_CLIP_BACK;
  543.         }
  544.         else if (v->bz > cw)
  545.         {
  546.                 local_outcode |= MGL_CLIP_FRONT;
  547.         }
  548.  
  549.         v->outcode = local_outcode;
  550.  
  551.     border |= local_outcode;
  552.  
  553.       v++;
  554.       } while (--i);
  555.  
  556.     #undef CLIP_EPS    
  557.    }
  558.  
  559.    #undef a
  560.  
  561.    return border;
  562. }
  563.  
  564.  
  565. INLINE void ProjectRange(GLcontext context, const int first, const int size)
  566. {
  567.    int i, stride;
  568.    float x,y,z,w;
  569.  
  570.    UBYTE *pointer;
  571.    float *wa;
  572.    float az;
  573.  
  574.    if(context->ZOffset_State == GL_TRUE)
  575.    {
  576.        az = context->az + context->ZOffset;
  577.    }
  578.    else
  579.    {
  580.     az = context->az;
  581.    }
  582.  
  583.    if(!(context->ClientState & GLCS_TEXTURE))
  584.    {
  585.        MGLVertex *v = &context->VertexBuffer[first];
  586.       i = size;
  587.  
  588.       do
  589.       {
  590.            x = v->bx;
  591.            y = v->by;
  592.            z = v->bz;
  593.            w = 1.0 / v->bw;
  594.         
  595.            v->bx = context->ax + x * w * context->sx;
  596.            v->by = context->ay - y * w * context->sy;
  597.            v->bz = az + z * w * context->sz;
  598.  
  599.       v++;
  600.  
  601.       } while (--i);
  602.    }
  603.    else if (context->ArrayPointer.FixpointTrans == GL_TRUE)
  604.    {
  605.        MGLVertex *v = &context->VertexBuffer[first];
  606.        stride = context->ArrayPointer.texcoordstride;
  607.        pointer = (UBYTE*)context->WBuffer + first * stride;
  608.  
  609.  
  610.       i = size;
  611.  
  612.       do
  613.       {
  614.            x = v->bx;
  615.            y = v->by;
  616.            z = v->bz;
  617.            w = 1.0 / v->bw;
  618.         
  619.            v->bx = context->ax + x * w * context->sx;
  620.            v->by = context->ay - y * w * context->sy;
  621.            v->bz = az + z * w * context->sz;
  622.  
  623.          w *= 32768.f;
  624.          wa = (float*)pointer;         
  625.          *wa = w;
  626.  
  627.       v++;
  628.       pointer += stride;
  629.  
  630.       } while (--i);
  631.    }
  632.    else
  633.    {
  634.        MGLVertex *v = &context->VertexBuffer[first];
  635.        stride = context->ArrayPointer.texcoordstride;
  636.        pointer = (UBYTE*)context->WBuffer + first * stride;
  637.  
  638.  
  639.       i = size;
  640.  
  641.       do
  642.       {
  643.            x = v->bx;
  644.            y = v->by;
  645.            z = v->bz;
  646.            w = 1.0 / v->bw;
  647.         
  648.            v->bx = context->ax + x * w * context->sx;
  649.            v->by = context->ay - y * w * context->sy;
  650.            v->bz = az + z * w * context->sz;
  651.  
  652.          wa = (float*)pointer;         
  653.          *wa = w;
  654.  
  655.       v++;
  656.       pointer += stride;
  657.  
  658.       } while (--i);
  659.    }
  660. }
  661.  
  662.  
  663. INLINE void ProjectRangeByOutcode(GLcontext context, const int first, const int size)
  664. {
  665.    int i, stride;
  666.    float x,y,z,w;
  667.  
  668.    UBYTE *pointer;
  669.    float *wa;
  670.    float az;
  671.  
  672.    if(context->ZOffset_State == GL_TRUE)
  673.    {
  674.        az = context->az + context->ZOffset;
  675.    }
  676.    else
  677.    {
  678.     az = context->az;
  679.    }
  680.  
  681.    if(context->ArrayPointer.FixpointTrans == GL_TRUE)
  682.    {
  683.     const float fix2float = 1.f/32768.f;
  684.  
  685.     if(!(context->ClientState & GLCS_TEXTURE))
  686.     {
  687.          MGLVertex *v = &context->VertexBuffer[first];
  688.  
  689.          for (i=0; i<size; i++, v++)
  690.          {
  691.            x = v->bx;
  692.            y = v->by;
  693.            z = v->bz;
  694.            w = v->bw;
  695.  
  696.          v->bx = fix2float * x;
  697.          v->by = fix2float * y;
  698.          v->bz = fix2float * z;
  699.          v->bw = fix2float * w;
  700.  
  701.          if(v->outcode & context->ClipFlags)
  702.         continue;
  703.  
  704.          w = 1.0 / w;
  705.  
  706.          v->v.x = context->ax + x * w * context->sx;
  707.          v->v.y = context->ay - y * w * context->sy;
  708.          v->v.z = az + z * w * context->sz;
  709.          }
  710.     }
  711.     else
  712.     {
  713.          MGLVertex *v = &context->VertexBuffer[first];
  714.          stride = context->ArrayPointer.texcoordstride;
  715.          pointer = (UBYTE*)context->WBuffer + first * stride;
  716.  
  717.          for (i=0; i<size; i++, v++, pointer += stride)
  718.          {
  719.            x = v->bx;
  720.            y = v->by;
  721.            z = v->bz;
  722.            w = v->bw;
  723.  
  724.          v->bx = fix2float * x;
  725.          v->by = fix2float * y;
  726.          v->bz = fix2float * z;
  727.          v->bw = fix2float * w;
  728.  
  729.          if(v->outcode & context->ClipFlags)
  730.         continue;
  731.  
  732.            w = 1.0 / w;
  733.         
  734.           v->v.x = context->ax + x * w * context->sx;
  735.          v->v.y = context->ay - y * w * context->sy;
  736.          v->v.z = az + z * w * context->sz;
  737.  
  738.          w *= 32768.f;
  739.          wa = (float*)pointer;         
  740.          v->v.w = w;
  741.          *wa = w;
  742.          }
  743.     }
  744.    }
  745.    else if(!(context->ClientState & GLCS_TEXTURE))
  746.    {
  747.         MGLVertex *v = &context->VertexBuffer[first];
  748.  
  749.       for (i=0; i<size; i++, v++)
  750.       {
  751.          if(v->outcode & context->ClipFlags)
  752.         continue;
  753.  
  754.            x = v->bx;
  755.            y = v->by;
  756.            z = v->bz;
  757.            w = 1.0 / v->bw;
  758.         
  759.          v->v.x = context->ax + x * w * context->sx;
  760.          v->v.y = context->ay - y * w * context->sy;
  761.          v->v.z = az + z * w * context->sz;
  762.        }
  763.    }
  764.    else
  765.    {
  766.        MGLVertex *v = &context->VertexBuffer[first];
  767.        stride = context->ArrayPointer.texcoordstride;
  768.        pointer = (UBYTE*)context->WBuffer + first * stride;
  769.  
  770.       for (i=0; i<size; i++, v++, pointer += stride)
  771.       {
  772.          if(v->outcode & context->ClipFlags)
  773.         continue;
  774.  
  775.            x = v->bx;
  776.            y = v->by;
  777.            z = v->bz;
  778.            w = 1.0 / v->bw;
  779.         
  780.          v->v.x = context->ax + x * w * context->sx;
  781.          v->v.y = context->ay - y * w * context->sy;
  782.          v->v.z = az + z * w * context->sz;
  783.  
  784.          v->v.w = w;
  785.  
  786.          wa = (float*)pointer;         
  787.          *wa = w;
  788.       }
  789.    }
  790. }
  791.  
  792.  
  793. INLINE void E_ToScreenArray(GLcontext context, const int count, const UWORD *idx)
  794. {
  795.    int i, stride;
  796.    float x,y,z,w;
  797.  
  798.    UBYTE *pointer;
  799.    float *wa;
  800.    float az;
  801.  
  802.    if(context->ZOffset_State == GL_TRUE)
  803.    {
  804.        az = context->az + context->ZOffset;
  805.    }
  806.    else
  807.    {
  808.     az = context->az;
  809.    }
  810.  
  811.    if(!(context->ClientState & GLCS_TEXTURE))
  812.    {
  813.       i = 0;
  814.  
  815.       do
  816.       {
  817.        MGLVertex *v = &context->VertexBuffer[idx[i]];
  818.  
  819.            x = v->bx;
  820.            y = v->by;
  821.            z = v->bz;
  822.            w = 1.0 / v->bw;
  823.         
  824.            v->v.x = context->ax + x * w * context->sx;
  825.            v->v.y = context->ay - y * w * context->sy;
  826.            v->v.z = az + z * w * context->sz;
  827.  
  828.       i++;
  829.       } while (i < count);
  830.    }
  831.    else
  832.    {
  833.        stride = context->ArrayPointer.texcoordstride;
  834.  
  835.       i = 0;
  836.  
  837.       do
  838.       {
  839.        MGLVertex *v = &context->VertexBuffer[idx[i]];
  840.  
  841.            x = v->bx;
  842.            y = v->by;
  843.            z = v->bz;
  844.            w = 1.0 / v->bw;
  845.         
  846.            v->v.x = context->ax + x * w * context->sx;
  847.            v->v.y = context->ay - y * w * context->sy;
  848.            v->v.z = az + z * w * context->sz;
  849.  
  850.        pointer = (UBYTE*)context->WBuffer + idx[i] * stride;
  851.     wa = (float*)pointer;         
  852.     *wa = w;
  853.  
  854.       i++;
  855.       } while (i < count);    
  856.    }
  857. }
  858.  
  859. INLINE void E_ToScreen(GLcontext context, int vnum)
  860. {
  861.     float *wa;
  862.     float w = 1.0/context->VertexBuffer[vnum].bw;
  863.     UBYTE *pointer = (UBYTE*)context->WBuffer + vnum * context->ArrayPointer.texcoordstride;
  864.  
  865.     context->VertexBuffer[vnum].v.x = context->ax + context->VertexBuffer[vnum].bx * w * context->sx;
  866.     context->VertexBuffer[vnum].v.y = context->ay - context->VertexBuffer[vnum].by * w * context->sy;
  867.     context->VertexBuffer[vnum].v.z = context->az + context->VertexBuffer[vnum].bz * w * context->sz;
  868.  
  869.     if (context->ZOffset_State == GL_TRUE)
  870.         context->VertexBuffer[vnum].v.z += (W3D_Float)context->ZOffset;
  871.  
  872.     context->VertexBuffer[vnum].v.w = w; 
  873.  
  874.     wa = (float*)pointer;
  875.     *wa = w;
  876. }
  877.  
  878. #ifdef __VBCC__
  879.  
  880. #define V_ToScreen(ctx,vnum){\
  881. static float wdiv;\
  882. wdiv = 1.0 / ctx->VertexBuffer[vnum].bw; \
  883. ctx->VertexBuffer[vnum].v.x = ctx->ax + ctx->VertexBuffer[vnum].bx * wdiv * ctx->sx; \
  884. ctx->VertexBuffer[vnum].v.y = ctx->ay - ctx->VertexBuffer[vnum].by * wdiv * ctx->sy; \
  885. ctx->VertexBuffer[vnum].v.z = ctx->az + ctx->VertexBuffer[vnum].bz * wdiv * ctx->sz; \
  886. if (ctx->ZOffset_State == GL_TRUE) ctx->VertexBuffer[vnum].v.z += (W3D_Float)ctx->ZOffset; \
  887. ctx->VertexBuffer[vnum].v.w = wdiv; \
  888. }
  889.  
  890. #else
  891.  
  892. static INLINE void V_ToScreen(GLcontext context, int vnum)
  893. {
  894.     GLfloat wdiv = 1.f / context->VertexBuffer[vnum].bw;
  895.  
  896.     context->VertexBuffer[vnum].v.x = (W3D_Float)(context->ax + context->VertexBuffer[vnum].bx * wdiv * context->sx);
  897.  
  898.     context->VertexBuffer[vnum].v.y = (W3D_Float)(context->ay - context->VertexBuffer[vnum].by * wdiv * context->sy);
  899.  
  900.     context->VertexBuffer[vnum].v.z = (W3D_Float)(context->az + context->VertexBuffer[vnum].bz * wdiv * context->sz);
  901.  
  902.     if (context->ZOffset_State == GL_TRUE) context->VertexBuffer[vnum].v.z += (W3D_Float)context->ZOffset; \
  903.  
  904.     context->VertexBuffer[vnum].v.w = (W3D_Float)wdiv; \
  905. }
  906.  
  907. #endif
  908.  
  909. void E_DrawPoints(GLcontext context, const int count, const UWORD *idx)
  910. {
  911. }
  912.  
  913. void E_DrawLines(GLcontext context, const int count, const UWORD *idx)
  914. {
  915. }
  916.  
  917. void E_DrawLineStrip(GLcontext context, const int count, const UWORD *idx)
  918. {
  919. }
  920.  
  921. void E_DrawLineLoop(GLcontext context, const int count, const UWORD *idx)
  922. {
  923. }
  924.  
  925. void E_DrawQuads(GLcontext context, const int count, const UWORD *idx)
  926. {
  927. }
  928.  
  929. void E_DrawQuadStrip(GLcontext context, const int count, const UWORD *idx)
  930. {
  931. }
  932.  
  933.  
  934. void E_DrawTriFan(GLcontext context, const int count, UWORD *idx)
  935. {
  936.       int i,j;
  937.     int size;
  938.     ULONG and_code, or_code, guard_band;
  939.       ULONG local_or, local_and;
  940.       ULONG error;
  941.       static W3D_Vertex **verts = NULL;
  942.       static W3D_TrianglesV fan;
  943.       static ULONG    complete[MGL_MAXVERTS];
  944.       static GLboolean visible[MGL_MAXVERTS];
  945.     static GLboolean projected[4096];
  946.       int first, triangle;
  947.       int cnum, pnum, backface, prevcopy, free;
  948.       int sign;
  949.  
  950.  
  951.     if(Clip_Volume_Bypass != GL_FALSE)
  952.     {
  953.        size = count;
  954.  
  955.        //first check if we are in guardband-mode
  956.        //and discard/shrink offscreen primitives
  957.  
  958.        if((Clip_Volume_Bypass > GL_TRUE) && context->VertexBuffer[idx[0]].outcode)
  959.        {
  960.         i = size - 2;
  961.  
  962.         local_and = context->VertexBuffer[idx[0]].outcode & context->VertexBuffer[idx[i]].outcode & context->VertexBuffer[idx[i+1]].outcode;
  963.  
  964.         if(local_and)
  965.         {
  966.             i--;
  967.  
  968.             while (i)
  969.             {
  970.                if((local_and & context->VertexBuffer[idx[i]].outcode) == 0)
  971.                 break;
  972.                i--;
  973.             }
  974.         }
  975.  
  976.         if(i == 0)
  977.         return;
  978.  
  979.         size = i+2;
  980.        }
  981.  
  982.  
  983.        if(context->CullFace_State == GL_FALSE)
  984.        {
  985.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, size, (void*)idx);
  986.        }
  987.        else
  988.        {
  989.        float fsign;
  990.        float area;
  991.        float x1,x2;
  992.        float y1,y2;
  993.  
  994.        #define x(a) (context->VertexBuffer[idx[a]].bx)
  995.        #define y(a) (context->VertexBuffer[idx[a]].by)
  996.  
  997.  
  998.         first = 0;
  999.         backface = 0;
  1000.  
  1001.         fsign = (float)(-context->CurrentCullSign);
  1002.  
  1003.         if(size == 3)
  1004.         {
  1005.             x1 = x(1) - x(0);
  1006.             y1 = y(1) - y(0);
  1007.             x2 = x(2) - x(0);
  1008.             y2 = y(2) - y(0);
  1009.  
  1010.             area = y2*x1 - x2*y1;
  1011.             area *= fsign;
  1012.         }
  1013.         else
  1014.         {
  1015.             float x0,y0;
  1016.             float area2;
  1017.  
  1018.             x0 = x(0);
  1019.             y0 = y(0);
  1020.      
  1021.             x1 = x(1) - x0;
  1022.              y1 = y(1) - y0;
  1023.             x2 = x(2) - x0;
  1024.             y2 = y(2) - y0;
  1025.  
  1026.             area = y2*x1 - x2*y1;
  1027.             area *= fsign;
  1028.  
  1029.             if(area < 0.f)
  1030.             {
  1031.                 first++;
  1032.                 area = 0.f;
  1033.             }
  1034.         
  1035.             i = 1;
  1036.             do
  1037.             {
  1038.                          x1 = x2;
  1039.                            y1 = y2;
  1040.                            x2 = x(i+2) - x0;
  1041.                            y2 = y(i+2) - y0;
  1042.  
  1043.                            area2 = y2*x1 - x2*y1;
  1044.                            area2 *= fsign;
  1045.     
  1046.                 if(area2 < 0.f)
  1047.                 {
  1048.                     if(first == i)
  1049.                         first++;
  1050.                                       else
  1051.                         backface++;
  1052.                 }
  1053.                 else
  1054.                 {
  1055.                                     backface = 0;
  1056.                                     area += area2;
  1057.                 }
  1058.  
  1059.             i++;
  1060.             } while (i < size-2);
  1061.         }
  1062.  
  1063.         if(area < context->MinTriArea)
  1064.             return;
  1065.  
  1066.         size -= backface + first; //shrink
  1067.  
  1068.         if(first)
  1069.         {
  1070.             UWORD val = idx[first];
  1071.  
  1072.             idx[first] = idx[0];
  1073.  
  1074.             error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, size, (void*)&idx[first]);
  1075.  
  1076.             idx[first] = val;
  1077.         }
  1078.         else
  1079.         {
  1080.  
  1081.             error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, size, (void*)idx);
  1082.  
  1083.         }
  1084.  
  1085.        #undef x
  1086.        #undef y
  1087.        }
  1088.     return;
  1089.     }
  1090.  
  1091.     sign = context->CurrentCullSign;
  1092.  
  1093.     if(context->ArrayPointer.transformed == GL_FALSE)
  1094.     {
  1095.         TransformIndex(context, count, idx);
  1096.     }
  1097.  
  1098.  
  1099.     or_code = 0;
  1100.     and_code = 0xff;
  1101.  
  1102.     for(i=0; i<count; i++)
  1103.     {
  1104.         and_code &= context->VertexBuffer[idx[i]].outcode;
  1105.         or_code |= context->VertexBuffer[idx[i]].outcode;
  1106.     }
  1107.  
  1108.     if(and_code)
  1109.         return;
  1110.  
  1111.     if(or_code == 0 || (or_code & context->ClipFlags))
  1112.     {
  1113.         guard_band = or_code;
  1114.     }
  1115.     else
  1116.     {
  1117.         float gcw;
  1118.         ULONG guard_code;
  1119.         MGLVertex *v;
  1120.  
  1121.         i = 0;
  1122.         guard_band = 0;
  1123.  
  1124.         do
  1125.         {
  1126.         v = &context->VertexBuffer[idx[i]];
  1127.  
  1128.         if(v->outcode)
  1129.         {
  1130.         gcw = v->bw * 2.0;
  1131.         guard_code = 0;
  1132.  
  1133.         if (-gcw > v->bx)
  1134.             guard_code |= MGL_CLIP_LEFT;
  1135.         else if (v->bx > gcw)
  1136.             guard_code |= MGL_CLIP_RIGHT;
  1137.  
  1138.         if (-gcw > v->by)
  1139.             guard_code |= MGL_CLIP_BOTTOM;
  1140.         else if (v->by > gcw)
  1141.             guard_code |= MGL_CLIP_TOP;
  1142.  
  1143.         guard_band |= guard_code;
  1144.         }
  1145.  
  1146.         i++;
  1147.         } while (i < count && guard_band == 0);
  1148.     }
  1149.  
  1150.     if (guard_band == 0)
  1151.     {
  1152.        if(context->ArrayPointer.transformed == GL_FALSE)
  1153.        E_ToScreenArray(context, count, idx);
  1154.  
  1155.        if(context->CullFace_State == GL_FALSE)
  1156.        {
  1157.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, count, (void*)idx);
  1158.        }
  1159.        else
  1160.        {
  1161.        float fsign;
  1162.        float area;
  1163.        float x1,x2;
  1164.        float y1,y2;
  1165.  
  1166.        #define x(a) (context->VertexBuffer[idx[a]].v.x)
  1167.        #define y(a) (context->VertexBuffer[idx[a]].v.y)
  1168.  
  1169.  
  1170.         fsign = (float)(-context->CurrentCullSign);
  1171.  
  1172.         first = 0;
  1173.         size = count;
  1174.         backface = 0;
  1175.  
  1176.         if(size == 3)
  1177.         {
  1178.             x1 = x(1) - x(0);
  1179.             y1 = y(1) - y(0);
  1180.             x2 = x(2) - x(0);
  1181.             y2 = y(2) - y(0);
  1182.  
  1183.             area = y2*x1 - x2*y1;
  1184.             area *= fsign;
  1185.         }
  1186.         else
  1187.         {
  1188.             float x0,y0;
  1189.             float area2;
  1190.  
  1191.             x0 = x(0);
  1192.             y0 = y(0);
  1193.      
  1194.             x1 = x(1) - x0;
  1195.              y1 = y(1) - y0;
  1196.             x2 = x(2) - x0;
  1197.             y2 = y(2) - y0;
  1198.  
  1199.             area = y2*x1 - x2*y1;
  1200.             area *= fsign;
  1201.  
  1202.             if(area < 0.f)
  1203.             {
  1204.                 first++;
  1205.                 area = 0.f;
  1206.             }
  1207.         
  1208.             i = 1;
  1209.             do
  1210.             {
  1211.                          x1 = x2;
  1212.                            y1 = y2;
  1213.                            x2 = x(i+2) - x0;
  1214.                            y2 = y(i+2) - y0;
  1215.  
  1216.                            area2 = y2*x1 - x2*y1;
  1217.                            area2 *= fsign;
  1218.     
  1219.                 if(area2 < 0.f)
  1220.                 {
  1221.                     if(first == i)
  1222.                         first++;
  1223.                                       else
  1224.                         backface++;
  1225.                 }
  1226.                 else
  1227.                 {
  1228.                                     backface = 0;
  1229.                                     area += area2;
  1230.                 }
  1231.  
  1232.             i++;
  1233.             } while (i < size-2);
  1234.         }
  1235.  
  1236.         if(area < context->MinTriArea)
  1237.             return;
  1238.  
  1239.         size -= backface + first; //shrink
  1240.  
  1241.         if(first)
  1242.         {
  1243.             UWORD val = idx[first];
  1244.  
  1245.             idx[first] = idx[0];
  1246.  
  1247.             error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, size, (void*)&idx[first]);
  1248.  
  1249.             idx[first] = val;
  1250.         }
  1251.         else
  1252.         {
  1253.             error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, size, (void*)idx);
  1254.         }
  1255.  
  1256.         #undef x
  1257.         #undef y
  1258.        }
  1259.  
  1260.     return;
  1261.     }
  1262.  
  1263.  
  1264.         if (verts == NULL)
  1265.         {
  1266.                 verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  1267.                 if (!verts) return;
  1268.         }
  1269.  
  1270.  
  1271.         backface = 0;
  1272.         triangle = 0;
  1273.         i = 1;
  1274.  
  1275.     if(context->CullFace_State == GL_FALSE)
  1276.     {
  1277.         do
  1278.         {
  1279.                 local_and = context->VertexBuffer[idx[0]].outcode
  1280.                         & context->VertexBuffer[idx[i]].outcode
  1281.                         & context->VertexBuffer[idx[i+1]].outcode;
  1282.  
  1283.                 local_or = context->VertexBuffer[idx[0]].outcode
  1284.                         | context->VertexBuffer[idx[i]].outcode
  1285.                         | context->VertexBuffer[idx[i+1]].outcode;
  1286.  
  1287.  
  1288.                 if (local_and == 0) // if the local and code is zero, we're not
  1289.                 {
  1290.             complete[triangle] = local_or;
  1291.             visible[triangle] = GL_TRUE;
  1292.             backface = 0;
  1293.                 }
  1294.                 else
  1295.                 {
  1296.                         visible[triangle] = GL_FALSE;    
  1297.                         backface++;
  1298.                 }
  1299.            i++;
  1300.            triangle++;
  1301.         } while ( i< count-1);
  1302.     }
  1303.     else
  1304.     {
  1305.         do
  1306.         {
  1307.                 local_and = context->VertexBuffer[idx[0]].outcode
  1308.                         & context->VertexBuffer[idx[i]].outcode
  1309.                         & context->VertexBuffer[idx[i+1]].outcode;
  1310.  
  1311.                 local_or = context->VertexBuffer[idx[0]].outcode
  1312.                         | context->VertexBuffer[idx[i]].outcode
  1313.                         | context->VertexBuffer[idx[i+1]].outcode;
  1314.  
  1315.  
  1316.                 if (local_and == 0) // if the local and code is zero, we're not
  1317.                 {
  1318.              complete[triangle] = local_or;
  1319.  
  1320.                    if(local_or & MGL_CLIP_NEGW)
  1321.                    {
  1322.                         visible[triangle] = GL_TRUE;
  1323.               backface = 0;
  1324.                    }
  1325.                    else
  1326.                    {
  1327.                         visible[triangle] = DecideFrontface(context, &(context->VertexBuffer[idx[0]]), &(context->VertexBuffer[idx[i]]), &(context->VertexBuffer[idx[i+1]]), sign);
  1328.  
  1329.                         if(!visible[triangle])
  1330.                 backface++;
  1331.               else
  1332.                 backface = 0;
  1333.                    }
  1334.                 }
  1335.                 else
  1336.                 {
  1337.                         visible[triangle] = GL_FALSE;    
  1338.                         backface++;
  1339.                 }
  1340.            i++;
  1341.            triangle++;
  1342.         } while ( i< count-1);
  1343.     }
  1344.  
  1345.         if(backface == triangle) //early out
  1346.         return;
  1347.  
  1348.       size = count - backface;
  1349.  
  1350.        Convert(context, idx[0]);
  1351.  
  1352.        prevcopy = 0;
  1353.       pnum = 0; 
  1354.       cnum = 0;
  1355.         free = context->VertexBufferPointer;
  1356.         triangle = 0; i = 1;
  1357.  
  1358.         do
  1359.         {
  1360.                 if (visible[triangle] == GL_FALSE) // case 3
  1361.                 {
  1362.                         triangle ++;
  1363.                         i        ++;
  1364.                 }
  1365.                 else
  1366.                 {
  1367.  
  1368.                         if (complete[triangle]) // case 1
  1369.                         {
  1370.                         clip[cnum].numverts = 3;
  1371.                         clip[cnum].verts[0] = idx[0];
  1372.                         clip[cnum].verts[1] = idx[i];
  1373.                         clip[cnum].verts[2] = idx[i+1];
  1374.  
  1375.               if(prevcopy != i)
  1376.               Convert(context, idx[i]);
  1377.  
  1378.               Convert(context, idx[i+1]);
  1379.               prevcopy = i+1;
  1380.  
  1381.                            AE_ClipPoly(context, &clip[cnum], free, complete[triangle]);
  1382.  
  1383.                            if(clip[cnum].numverts)
  1384.                            {
  1385.                               free = clip[cnum].nextfree;
  1386.                               cnum++;
  1387.                            }
  1388.  
  1389.                            triangle++; i++;
  1390.                         }
  1391.                         else
  1392.                         {   // case 2 (the difficult part)
  1393.                         int k=3;
  1394.                         polys[pnum].verts[0] = idx[0];
  1395.                         polys[pnum].verts[1] = idx[i];
  1396.                         polys[pnum].verts[2] = idx[i+1];
  1397.  
  1398.                             triangle++; i++;
  1399.  
  1400.                             while (complete[triangle]==0 && visible[triangle] && i<size-1)
  1401.                             {
  1402.                             polys[pnum].verts[k] = idx[i+1];
  1403.  
  1404.                             i++; k++; triangle++;
  1405.                             }
  1406.  
  1407.                         polys[pnum].numverts = k;
  1408.                         pnum++;
  1409.                         }
  1410.                 }
  1411.         } while (i<size-1);
  1412.  
  1413.  
  1414. //Project to screen and draw:
  1415.  
  1416.   if(cnum)
  1417.   {
  1418.     if(context->ArrayPointer.transformed == GL_FALSE)
  1419.     {
  1420.       for(i=0; i<size; i++)
  1421.       {  
  1422.          projected[idx[i]] = GL_FALSE;
  1423.        }
  1424.     }
  1425.  
  1426.     for(i=context->VertexBufferPointer; i<free; i++)
  1427.     {
  1428.         V_ToScreen(context, i);
  1429.     }
  1430.  
  1431.   }
  1432.  
  1433.   if(pnum)
  1434.   {
  1435.       PolyBuffer *p;
  1436.  
  1437.       p = &polys[0];
  1438.  
  1439.     if(context->ArrayPointer.transformed == GL_FALSE)
  1440.     {
  1441.         E_ToScreen(context, p->verts[0]);
  1442.         E_ToScreen(context, p->verts[1]);
  1443.         E_ToScreen(context, p->verts[2]);
  1444.     
  1445.         projected[p->verts[0]] = GL_TRUE;
  1446.         projected[p->verts[1]] = GL_TRUE;
  1447.         projected[p->verts[2]] = GL_TRUE;
  1448.  
  1449.         if(p->numverts > 3)
  1450.         {
  1451.         i=3;
  1452.                 do
  1453.                 {
  1454.                         E_ToScreen(context, p->verts[i]);
  1455.                         projected[p->verts[i]] = GL_TRUE;
  1456.                 i++;
  1457.                 } while (i < p->numverts);
  1458.         }
  1459.     }
  1460.  
  1461.     error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_ULONG, p->numverts, (void*)p->verts);
  1462.  
  1463.     j = 1;
  1464.     while (j < pnum)
  1465.     {
  1466.         p = &polys[j];
  1467.  
  1468.         if(context->ArrayPointer.transformed == GL_FALSE)
  1469.         {
  1470.                 E_ToScreen(context, p->verts[1]);
  1471.                 E_ToScreen(context, p->verts[2]);
  1472.  
  1473.                 projected[p->verts[1]] = GL_TRUE;
  1474.                 projected[p->verts[2]] = GL_TRUE;
  1475.  
  1476.  
  1477.                 if(p->numverts > 3)
  1478.                 {
  1479.                 i=3;
  1480.  
  1481.                    do
  1482.                    {
  1483.                         E_ToScreen(context,  p->verts[i]);
  1484.                         projected[p->verts[i]] = GL_TRUE;
  1485.                    i++;
  1486.                    } while (i < p->numverts);
  1487.                 }
  1488.         }
  1489.  
  1490.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_ULONG, p->numverts, (void*)p->verts);
  1491.  
  1492.     j++;
  1493.     }
  1494.   }
  1495.  
  1496.   if(cnum)
  1497.   {
  1498.   fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  1499.   fan.st_pattern = NULL;
  1500.  
  1501.     j = 0;
  1502.  
  1503.     do
  1504.     {
  1505.     PolyBuffer *p = &clip[j];
  1506.  
  1507.     if(context->ArrayPointer.transformed == GL_FALSE)
  1508.     {
  1509.         for (i=0; i<p->numverts; i++)
  1510.         {
  1511.           int vert = p->verts[i];
  1512.  
  1513.           verts[i] = &(context->VertexBuffer[vert].v);
  1514.  
  1515.           if(vert < context->VertexBufferPointer && projected[vert] == GL_FALSE)
  1516.           {
  1517.                 V_ToScreen(context, vert);
  1518.                 projected[vert] = GL_TRUE; 
  1519.           }
  1520.  
  1521.         }
  1522.     }
  1523.     else
  1524.     {
  1525.         for (i=0; i<p->numverts; i++)
  1526.         {
  1527.             verts[i] = &(context->VertexBuffer[p->verts[i]].v);
  1528.         }
  1529.     }
  1530.  
  1531.     fan.vertexcount = p->numverts;
  1532.     fan.v = verts;
  1533.     error = W3D_DrawTriFanV(context->w3dContext, &fan);
  1534.  
  1535.     j++;
  1536.  
  1537.     } while (j < cnum);
  1538.   }
  1539. }
  1540.  
  1541.  
  1542. void E_DrawTriStrip(GLcontext context, const int count, const UWORD *idx)
  1543. {
  1544.       int i,j;
  1545.     int size;
  1546.     ULONG and_code, or_code, guard_band;
  1547.       ULONG local_or, local_and;
  1548.       ULONG error;
  1549.       static W3D_Vertex **verts = NULL;
  1550.       static W3D_TrianglesV tris;
  1551.       static ULONG    complete[MGL_MAXVERTS];
  1552.       static GLboolean visible[MGL_MAXVERTS];
  1553.     static GLboolean projected[4096];
  1554.       int first;
  1555.       int cnum, pnum, backface, prevcopy, free;
  1556.  
  1557.  
  1558.     if(Clip_Volume_Bypass != GL_FALSE)
  1559.     {
  1560.        size = count;
  1561.        first = 0;
  1562.  
  1563.        //first check if we are in guardband-mode
  1564.        //and discard/shrink offscreen primitives
  1565.  
  1566.        if((Clip_Volume_Bypass > GL_TRUE) && (context->VertexBuffer[idx[0]].outcode || context->VertexBuffer[idx[size-1]].outcode))
  1567.        {
  1568.         i = size - 3;
  1569.  
  1570.         local_and = context->VertexBuffer[idx[i]].outcode & context->VertexBuffer[idx[i+1]].outcode & context->VertexBuffer[idx[i+2]].outcode;
  1571.  
  1572.         if(local_and)
  1573.         {
  1574.             i--;
  1575.  
  1576.             while (i >= 0)
  1577.             {
  1578.                if((local_and & context->VertexBuffer[idx[i]].outcode) == 0)
  1579.                 break;
  1580.                i--;
  1581.             }
  1582.         }
  1583.  
  1584.         if(i < 0)
  1585.         return;
  1586.  
  1587.         size = i+3;
  1588.  
  1589.         if(size > 3)
  1590.         {
  1591.             local_and = context->VertexBuffer[idx[0]].outcode & context->VertexBuffer[idx[1]].outcode & context->VertexBuffer[idx[2]].outcode;
  1592.  
  1593.             i = 2;
  1594.  
  1595.             if(local_and)
  1596.             {
  1597.                i++;
  1598.  
  1599.                while(i < size-1)
  1600.                {
  1601.                 if((local_and & context->VertexBuffer[idx[i]].outcode) == 0)
  1602.                     break;
  1603.                 i++;
  1604.  
  1605.                }
  1606.             }
  1607.  
  1608.             first = i-2;
  1609.         }
  1610.        }
  1611.  
  1612.        if(context->CullFace_State == GL_FALSE)
  1613.        {
  1614.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, W3D_INDEX_UWORD, size-first, (void*)&idx[first]);
  1615.        }
  1616.        else
  1617.        {
  1618.         float fsign;
  1619.         float area;
  1620.         float x1,x2;
  1621.         float y1,y2;
  1622.  
  1623.         #define x(a) (context->VertexBuffer[idx[a]].bx)
  1624.         #define y(a) (context->VertexBuffer[idx[a]].by)
  1625.  
  1626.         backface = 0;
  1627.  
  1628.         fsign = (float)(-context->CurrentCullSign);
  1629.         if(first % 2) fsign = -fsign;
  1630.  
  1631.                     if(size == 3)
  1632.                   {
  1633.                         x1 = x(first+1) - x(first);
  1634.                         y1 = y(first+1) - y(first);
  1635.                         x2 = x(first+2) - x(first);
  1636.                         y2 = y(first+2) - y(first);
  1637.  
  1638.                         area = y2*x1 - x2*y1;
  1639.                         area *= fsign;
  1640.               }
  1641.               else
  1642.               {
  1643.                   float a1,a2,b1,b2;
  1644.                   float area2;
  1645.  
  1646.                          i = first+1;
  1647.  
  1648.                         a1 = x(i);
  1649.                         b1 = y(i);
  1650.                         a2 = x(i+1);
  1651.                         b2 = y(i+1);
  1652.  
  1653.                         x1 = a1 - x(first);
  1654.                         y1 = b1 - y(first);
  1655.                         x2 = a2 - x(first);
  1656.                         y2 = b2 - y(first);
  1657.  
  1658.                         area = y2*x1 - x2*y1;
  1659.                   area *= fsign;
  1660.  
  1661.  
  1662.                            if(area < 0.f)
  1663.                            {
  1664.                                 first++;
  1665.                                 area = 0.f;
  1666.                            }
  1667.  
  1668.         
  1669.                             do
  1670.                            {
  1671.                            fsign = -fsign;
  1672.  
  1673.                            x1 = a2 - a1;
  1674.                            y1 = b2 - b1;
  1675.                            x2 = x(i+2) - a1;
  1676.                            y2 = y(i+2) - b1;
  1677.                            a1 = a2;
  1678.                           b1 = b2;
  1679.                            a2 = x(i+2);
  1680.                            b2 = y(i+2);
  1681.  
  1682.                            area2 = y2*x1 - x2*y1;
  1683.                            area2 *= fsign;
  1684.     
  1685.                               if(area2 < 0.f)
  1686.                               {
  1687.                   if(first == i)
  1688.                     first++;
  1689.                   else
  1690.                                       backface++;
  1691.                             }
  1692.                             else
  1693.                               {
  1694.                                     backface = 0;
  1695.                                     area += area2;
  1696.                               }
  1697.  
  1698.                            i++;
  1699.                            } while (i < size-2);
  1700.  
  1701.             size -= backface + first;
  1702.             }
  1703.  
  1704.         if(area < context->MinTriArea)
  1705.             return;
  1706.  
  1707.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, W3D_INDEX_UWORD, size, (void*)&idx[first]);
  1708.  
  1709.         #undef x
  1710.         #undef y
  1711.        }
  1712.     return;
  1713.     }
  1714.  
  1715.  
  1716.     if(context->ArrayPointer.transformed == GL_FALSE)
  1717.     {
  1718.         TransformIndex(context, count, idx);
  1719.     }
  1720.  
  1721.     or_code = 0;
  1722.     and_code = 0xff;
  1723.  
  1724.     for(i=0; i<count; i++)
  1725.     {
  1726.         and_code &= context->VertexBuffer[idx[i]].outcode;
  1727.         or_code |= context->VertexBuffer[idx[i]].outcode;
  1728.     }
  1729.  
  1730.     if(and_code)
  1731.         return;
  1732.  
  1733.     if(or_code == 0 || (or_code & context->ClipFlags))
  1734.     {
  1735.         guard_band = or_code;
  1736.     }
  1737.     else
  1738.     {
  1739.         float gcw;
  1740.         ULONG guard_code;
  1741.         MGLVertex *v;
  1742.  
  1743.         i = 0;
  1744.         guard_band = 0;
  1745.  
  1746.         do
  1747.         {
  1748.         v = &context->VertexBuffer[idx[i]];
  1749.  
  1750.         if(v->outcode)
  1751.         {
  1752.         gcw = v->bw * 2.0;
  1753.         guard_code = 0;
  1754.  
  1755.         if (-gcw > v->bx)
  1756.             guard_code |= MGL_CLIP_LEFT;
  1757.         else if (v->bx > gcw)
  1758.             guard_code |= MGL_CLIP_RIGHT;
  1759.  
  1760.         if (-gcw > v->by)
  1761.             guard_code |= MGL_CLIP_BOTTOM;
  1762.         else if (v->by > gcw)
  1763.             guard_code |= MGL_CLIP_TOP;
  1764.  
  1765.         guard_band |= guard_code;
  1766.         }
  1767.  
  1768.         i++;
  1769.         } while (i < count && guard_band == 0);
  1770.     }
  1771.  
  1772.     if (guard_band == 0)
  1773.     {
  1774.         if(context->ArrayPointer.transformed == GL_FALSE)
  1775.         E_ToScreenArray(context, count, idx);
  1776.  
  1777.         if(context->CullFace_State == GL_FALSE)
  1778.         {
  1779.             error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, W3D_INDEX_UWORD, count, (void*)idx);
  1780.  
  1781.         }
  1782.         else
  1783.         {
  1784.         #define x(a) (context->VertexBuffer[idx[a]].v.x)
  1785.         #define y(a) (context->VertexBuffer[idx[a]].v.y)
  1786.  
  1787.         float fsign;
  1788.         float area;
  1789.         float x1,x2;
  1790.         float y1,y2;
  1791.  
  1792.         fsign = (float)(-context->CurrentCullSign);
  1793.  
  1794.         size = count;
  1795.         backface = 0;
  1796.         first = 0;
  1797.  
  1798.  
  1799.                     if(size == 3)
  1800.                   {
  1801.                         x1 = x(1) - x(0);
  1802.                         y1 = y(1) - y(0);
  1803.                         x2 = x(2) - x(0);
  1804.                         y2 = y(2) - y(0);
  1805.  
  1806.                         area = y2*x1 - x2*y1;
  1807.                         area *= fsign;
  1808.               }
  1809.               else
  1810.               {
  1811.                   float a1,a2,b1,b2;
  1812.                   float area2;
  1813.  
  1814.                         a1 = x(1);
  1815.                         b1 = y(1);
  1816.                         a2 = x(2);
  1817.                         b2 = y(2);
  1818.  
  1819.                         x1 = a1 - x(0);
  1820.                         y1 = b1 - y(0);
  1821.                         x2 = a2 - x(0);
  1822.                         y2 = b2 - y(0);
  1823.  
  1824.                         area = y2*x1 - x2*y1;
  1825.                   area *= fsign;
  1826.  
  1827.                            if(area < 0.f)
  1828.                            {
  1829.                                 first++;
  1830.                                 area = 0.f;
  1831.                            }
  1832.         
  1833.                            i = 1;
  1834.                            do
  1835.                            {
  1836.                            fsign = -fsign;
  1837.                            x1 = a2 - a1;
  1838.                            y1 = b2 - b1;
  1839.                            x2 = x(i+2) - a1;
  1840.                            y2 = y(i+2) - b1;
  1841.                            a1 = a2;
  1842.                           b1 = b2;
  1843.                            a2 = x(i+2);
  1844.                            b2 = y(i+2);
  1845.  
  1846.                            area2 = y2*x1 - x2*y1;
  1847.                            area2 *= fsign;
  1848.     
  1849.                               if(area2 < 0.f)
  1850.                               {
  1851.                   if(first == i)
  1852.                     first++;
  1853.                   else
  1854.                                       backface++;
  1855.                             }
  1856.                             else
  1857.                               {
  1858.                                     backface = 0;
  1859.                                     area += area2;
  1860.                               }
  1861.  
  1862.                            i++;
  1863.                            } while (i < size-2);
  1864.  
  1865.             size -= first + backface;
  1866.             }
  1867.  
  1868.         if(area < context->MinTriArea)
  1869.             return;
  1870.  
  1871.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, W3D_INDEX_UWORD, size, (void*)&idx[first]); 
  1872.  
  1873.         #undef x
  1874.         #undef y
  1875.  
  1876.         }
  1877.  
  1878.     return;
  1879.     }
  1880.  
  1881.  
  1882.     if (verts == NULL)
  1883.     {
  1884.                 verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  1885.                 if (!verts) return;
  1886.     }
  1887.  
  1888.  
  1889.     backface = 0;
  1890.     i = 0;
  1891.  
  1892.       do
  1893.       {
  1894.                 local_and = context->VertexBuffer[idx[i]].outcode
  1895.                         & context->VertexBuffer[idx[i+1]].outcode
  1896.                         & context->VertexBuffer[idx[i+2]].outcode;
  1897.  
  1898.                 local_or = context->VertexBuffer[idx[i]].outcode
  1899.                         | context->VertexBuffer[idx[i+1]].outcode
  1900.                         | context->VertexBuffer[idx[i+2]].outcode;
  1901.  
  1902.                 if (local_and == 0) // if the local and code is zero, we're not
  1903.                 {
  1904.             complete[i] = local_or;
  1905.             visible[i] = GL_TRUE;
  1906.             backface = 0;
  1907.                 }
  1908.                 else
  1909.                 {
  1910.                         visible[i] = GL_FALSE;    
  1911.                         backface++;
  1912.                 }
  1913.  
  1914.       i++;
  1915.     } while (i < count-2);
  1916.  
  1917.     size = count - backface;
  1918.  
  1919.       free = context->VertexBufferPointer;
  1920.  
  1921.     prevcopy = -1;
  1922.     pnum = 0;
  1923.       cnum = 0;
  1924.       i = 0;
  1925.  
  1926.         do
  1927.         {
  1928.                 if (visible[i] == GL_FALSE) // case 3
  1929.                 {
  1930.                         i++;
  1931.                 }
  1932.                 else if (complete[i]) // case 1
  1933.                 {
  1934.                         clip[cnum].numverts = 3;
  1935.  
  1936.                         clip[cnum].verts[0] = idx[i];
  1937.                         clip[cnum].verts[1] = idx[i+1];
  1938.                         clip[cnum].verts[2] = idx[i+2];
  1939.  
  1940. //this element is never shared with next triangle:
  1941.  
  1942.                         if(prevcopy == i+1)
  1943.                         {
  1944.                                 Convert(context, idx[i+2]);
  1945.                         }
  1946.                         else if(prevcopy == i)
  1947.                         {
  1948.                                 Convert(context, idx[i+1]);
  1949.                                 Convert(context, idx[i+2]);
  1950.                         }
  1951.               else
  1952.               {
  1953.                                 Convert(context, idx[i+0]);
  1954.                                 Convert(context, idx[i+1]);
  1955.                                 Convert(context, idx[i+2]);
  1956.               }
  1957.  
  1958. //this element is never shared with previous triangle:
  1959.  
  1960.                         prevcopy = i+2;
  1961.  
  1962.  
  1963.                         AE_ClipPoly(context, &clip[cnum], free, complete[i]);
  1964.                         i++;
  1965.  
  1966.                         if(clip[cnum].numverts)
  1967.                         {
  1968.                               free = clip[cnum].nextfree;
  1969.                               cnum++;
  1970.                         }
  1971.                 }
  1972.                 else
  1973.                 {   // case 2 (the difficult part)
  1974.  
  1975.               int k = 3;
  1976.                         polys[pnum].verts[0] = i;
  1977.                         i++;
  1978.  
  1979.                         while (complete[i]==0 && visible[i] == GL_TRUE && i<size-2 && k < 64)
  1980.                         {
  1981.                                 i++; k++;
  1982.                         }
  1983.  
  1984.                         polys[pnum].numverts = k;
  1985.                         pnum++;
  1986.                 }
  1987.         } while (i < size-2);
  1988.  
  1989.  
  1990. //Project to screen and draw:
  1991.  
  1992.   if(cnum)
  1993.   {
  1994.     if(context->ArrayPointer.transformed == GL_FALSE)
  1995.     {
  1996.        for(i=0; i<size; i++)
  1997.        {
  1998.         projected[idx[i]] = GL_FALSE;
  1999.        }
  2000.     }
  2001.  
  2002.     for(i=context->VertexBufferPointer; i<free; i++)
  2003.     {
  2004.         V_ToScreen(context, i);
  2005.     }
  2006.   }
  2007.  
  2008.   if(pnum)
  2009.   {
  2010.     PolyBuffer *p;
  2011.     int start;
  2012.  
  2013.       p = &polys[0];
  2014.     start = p->verts[0];
  2015.  
  2016.     if(context->ArrayPointer.transformed == GL_FALSE)
  2017.     {
  2018.         E_ToScreen(context, idx[start+0]);
  2019.         E_ToScreen(context, idx[start+1]);
  2020.         E_ToScreen(context, idx[start+2]);
  2021.  
  2022.         projected[idx[start+0]] = GL_TRUE;
  2023.         projected[idx[start+1]] = GL_TRUE;
  2024.         projected[idx[start+2]] = GL_TRUE;
  2025.  
  2026.         i=3;
  2027.         while(i < p->numverts)
  2028.         {
  2029.          E_ToScreen(context, idx[start+i]);
  2030.          projected[idx[start+i]] = GL_TRUE;
  2031.         i++;
  2032.       }
  2033.       }
  2034.  
  2035.     error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, W3D_INDEX_UWORD, p->numverts, (void*)&idx[start]);
  2036.  
  2037.       j = 1;
  2038.  
  2039.       while (j < pnum)
  2040.       {
  2041.               p = &polys[j];
  2042.           start = p->verts[0];
  2043.  
  2044.         if(context->ArrayPointer.transformed == GL_FALSE)
  2045.         {
  2046.      
  2047.                 if(projected[idx[start+0]] == GL_FALSE)
  2048.                 E_ToScreen(context, idx[start+0]);
  2049.  
  2050.                 E_ToScreen(context, idx[start+1]);
  2051.                 E_ToScreen(context, idx[start+2]);
  2052.  
  2053.                 projected[idx[start+0]] = GL_TRUE;
  2054.                   projected[idx[start+1]] = GL_TRUE;
  2055.                 projected[idx[start+2]] = GL_TRUE;
  2056.  
  2057.               i=3;
  2058.                 while(i < p->numverts)
  2059.                 {               
  2060.                         E_ToScreen(context, idx[start+i]);
  2061.                         projected[idx[start+i]] = GL_TRUE;
  2062.                 i++;
  2063.                 }
  2064.         }
  2065.  
  2066.        error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRISTRIP, W3D_INDEX_UWORD, p->numverts, (void*)&idx[start]);
  2067.  
  2068.     j++;
  2069.       }
  2070.   }
  2071.  
  2072.   if(cnum)
  2073.   {
  2074.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  2075.     tris.st_pattern = NULL;
  2076.  
  2077.     j = 0;
  2078.  
  2079.     do
  2080.     {
  2081.     PolyBuffer *p = &clip[j];
  2082.  
  2083.     if(context->ArrayPointer.transformed == GL_FALSE)
  2084.     {
  2085.         for (i=0; i<p->numverts; i++)
  2086.         {
  2087.           int vert = p->verts[i];
  2088.  
  2089.           verts[i] = &(context->VertexBuffer[vert].v);
  2090.  
  2091.           if(vert < context->VertexBufferPointer && projected[vert] == GL_FALSE)
  2092.           {
  2093.                 V_ToScreen(context, vert);
  2094.                 projected[vert] = GL_TRUE; 
  2095.           }
  2096.  
  2097.         }
  2098.     }
  2099.     else
  2100.     {
  2101.         for (i=0; i<p->numverts; i++)
  2102.         {
  2103.             verts[i] = &(context->VertexBuffer[p->verts[i]].v);
  2104.         }
  2105.     }
  2106.  
  2107.     tris.vertexcount = p->numverts;
  2108.     tris.v = verts;
  2109.  
  2110.     error = W3D_DrawTriFanV(context->w3dContext, &tris);
  2111.  
  2112.     j++;
  2113.     } while (j < cnum);
  2114.   }
  2115. }
  2116.  
  2117.  
  2118. //added 27-05-02
  2119.  
  2120. void E_DrawTriangles_Locked(GLcontext context, const int count, const UWORD *idx)
  2121. {
  2122.       int i, j;
  2123.     ULONG local_and, local_or;
  2124.       ULONG error;
  2125.       static W3D_Vertex **verts = NULL;
  2126.       static W3D_TrianglesV fan;
  2127.     static ULONG trichain[MGL_MAXVERTS*3];
  2128.       static int sign;
  2129.     GLboolean visible;
  2130.       int cnum, free, chainverts;
  2131.  
  2132.     sign = context->CurrentCullSign;
  2133.  
  2134.     if(Clip_Volume_Bypass != GL_FALSE)
  2135.     {
  2136.     chainverts = 0;
  2137.  
  2138.         if(Clip_Volume_Bypass == GL_TRUE)
  2139.         {
  2140.            if(context->CullFace_State == GL_FALSE)
  2141.            {
  2142.             error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, W3D_INDEX_UWORD, count, (void *)idx);
  2143.            }
  2144.            else
  2145.            {
  2146.             for(i=0; i<count; i+=3)
  2147.             {
  2148.                if(E_CheckTri(context, &context->VertexBuffer[idx[i]], &context->VertexBuffer[idx[i+1]], &context->VertexBuffer[idx[i+2]], sign) == GL_TRUE)
  2149.                {
  2150.                 trichain[chainverts+0] = idx[i+0];
  2151.                 trichain[chainverts+1] = idx[i+1];
  2152.                 trichain[chainverts+2] = idx[i+2];
  2153.                 chainverts+=3; 
  2154.                }
  2155.             }
  2156.  
  2157.            }
  2158.         }
  2159.         else
  2160.         {
  2161.            if(context->CullFace_State == GL_FALSE)
  2162.            for(i=0; i<count; i+=3)
  2163.            {
  2164.                   local_and = context->VertexBuffer[idx[i]].outcode & context->VertexBuffer[idx[i+1]].outcode & context->VertexBuffer[idx[i+2]].outcode;
  2165.  
  2166.                if(local_and == 0)
  2167.                {
  2168.  
  2169.                 trichain[chainverts+0] = idx[i+0];
  2170.                 trichain[chainverts+1] = idx[i+1];
  2171.                 trichain[chainverts+2] = idx[i+2];
  2172.                 chainverts+=3;
  2173.                }
  2174.            }
  2175.            else        
  2176.            for(i=0; i<count; i+=3)
  2177.            {
  2178.                local_and = context->VertexBuffer[idx[i]].outcode & context->VertexBuffer[idx[i+1]].outcode & context->VertexBuffer[idx[i+2]].outcode;
  2179.  
  2180.             if(local_and == 0)
  2181.             {
  2182.  
  2183.                if(E_CheckTri(context, &context->VertexBuffer[idx[i]], &context->VertexBuffer[idx[i+1]], &context->VertexBuffer[idx[i+2]], sign) == GL_TRUE)
  2184.                {
  2185.                 trichain[chainverts+0] = idx[i+0];
  2186.                 trichain[chainverts+1] = idx[i+1];
  2187.                 trichain[chainverts+2] = idx[i+2];
  2188.                 chainverts+=3;
  2189.                }
  2190.             }
  2191.            }
  2192.         }
  2193.  
  2194.     if(chainverts)
  2195.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, W3D_INDEX_ULONG, chainverts, (void *)trichain);
  2196.  
  2197.     return;
  2198.     }
  2199.  
  2200.     free = context->VertexBufferPointer;
  2201.     chainverts = 0;
  2202.     cnum = 0;
  2203.     i = 0;
  2204.  
  2205.     do
  2206.     {
  2207.        local_and = context->VertexBuffer[idx[i]].outcode & context->VertexBuffer[idx[i+1]].outcode & context->VertexBuffer[idx[i+2]].outcode;
  2208.  
  2209.        local_or = context->VertexBuffer[idx[i]].outcode | context->VertexBuffer[idx[i+1]].outcode | context->VertexBuffer[idx[i+2]].outcode;
  2210.  
  2211.        if(local_and)
  2212.        {
  2213.         i+=3;
  2214.        }
  2215.        else
  2216.        {
  2217.         if (local_or == 0)
  2218.         {
  2219.            if(context->CullFace_State == GL_FALSE)
  2220.            {
  2221.                visible = GL_TRUE;
  2222.            }
  2223.            else
  2224.            {
  2225.                      visible = E_CheckTri(context, &context->VertexBuffer[idx[i]], &context->VertexBuffer[idx[i+1]], &context->VertexBuffer[idx[i+2]], sign);
  2226.            }
  2227.  
  2228.                  if(visible)
  2229.                 {
  2230.                trichain[chainverts+0] = idx[i+0];
  2231.                trichain[chainverts+1] = idx[i+1];
  2232.                trichain[chainverts+2] = idx[i+2];
  2233.                chainverts += 3;
  2234.            }
  2235.             }
  2236.             else
  2237.             {
  2238.                if(context->CullFace_State == GL_FALSE || (local_or & MGL_CLIP_NEGW))
  2239.                {
  2240.              visible = GL_TRUE;
  2241.                  }
  2242.            else
  2243.                {
  2244.             visible = DecideFrontface(context, &(context->VertexBuffer[idx[i]]), &(context->VertexBuffer[idx[i+1]]), &(context->VertexBuffer[idx[i+2]]), sign);
  2245.                }
  2246.  
  2247.                if(visible)
  2248.                {
  2249.                    Convert(context, idx[i]);
  2250.                    Convert(context, idx[i+1]);
  2251.                    Convert(context, idx[i+2]);
  2252.  
  2253.                    clip[cnum].numverts = 3;
  2254.                    clip[cnum].verts[0] = idx[i];
  2255.                    clip[cnum].verts[1] = idx[i+1];
  2256.                    clip[cnum].verts[2] = idx[i+2];
  2257.  
  2258.                    AE_ClipPoly(context, &clip[cnum], free, local_or);
  2259.  
  2260.                    if(clip[cnum].numverts)
  2261.                    {
  2262.             free = clip[cnum].nextfree;
  2263.             cnum++;
  2264.                    }
  2265.                }
  2266.             }
  2267.         i+=3;
  2268.         }
  2269.     } while (i < count);
  2270.  
  2271.  
  2272.     if(chainverts)
  2273.     {
  2274.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, W3D_INDEX_ULONG, chainverts, (void*)&trichain[0]);
  2275.     }
  2276.  
  2277.  
  2278.       if (cnum)
  2279.     {
  2280.     static PolyBuffer *p;
  2281.     static int start;
  2282.  
  2283.        if(verts == NULL)
  2284.        {
  2285.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  2286.                   if (!verts) return;
  2287.        }
  2288.  
  2289.        for(i=context->VertexBufferPointer; i<free; i++)
  2290.        {
  2291.         V_ToScreen(context, i);
  2292.        } 
  2293.  
  2294.        fan.st_pattern = NULL;
  2295.        fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2296.  
  2297.        start = 0;
  2298.        i = 0;
  2299.  
  2300.         do
  2301.         {
  2302.            p = &clip[i];
  2303.            j = 0;
  2304.  
  2305.         while (j < p->numverts)
  2306.         {
  2307.             verts[start+j] = &(context->VertexBuffer[p->verts[j]].v);
  2308.  
  2309.             j++;
  2310.         }
  2311.  
  2312.         fan.v = &verts[start];
  2313.         fan.vertexcount = p->numverts;
  2314.         start += p->numverts;
  2315.  
  2316.         error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2317.         i++;
  2318.         } while (i < cnum);
  2319.       }
  2320. }
  2321.  
  2322.  
  2323. void E_DrawTriangles(GLcontext context, const int count, const UWORD *idx)
  2324. {
  2325.       int i, j;
  2326.     ULONG local_and, local_or;
  2327.       ULONG error;
  2328.       static W3D_Vertex **verts = NULL;
  2329.       static W3D_TrianglesV fan;
  2330.     static ULONG trichain[MGL_MAXVERTS*3]; //should be enough
  2331.       static GLboolean visible;
  2332.       static int sign;
  2333.       int cnum, free, chainverts;
  2334.  
  2335.     if(context->ArrayPointer.transformed == GL_TRUE)
  2336.     {
  2337.         E_DrawTriangles_Locked(context, count, idx);
  2338.             return;
  2339.     }
  2340.  
  2341.     sign = context->CurrentCullSign;
  2342.  
  2343.     TransformIndex(context, count, idx);
  2344.  
  2345.     free = context->VertexBufferPointer;
  2346.     chainverts = 0;
  2347.     cnum = 0;
  2348.     i = 0;
  2349.  
  2350.     do
  2351.     {
  2352.        local_and = context->VertexBuffer[idx[i]].outcode & context->VertexBuffer[idx[i+1]].outcode & context->VertexBuffer[idx[i+2]].outcode;
  2353.  
  2354.        local_or = context->VertexBuffer[idx[i]].outcode | context->VertexBuffer[idx[i+1]].outcode | context->VertexBuffer[idx[i+2]].outcode;
  2355.  
  2356.        if(local_and)
  2357.        {
  2358.         i+=3;
  2359.        }
  2360.        else
  2361.        {
  2362.         if (local_or == 0)
  2363.         {
  2364.                  E_ToScreen(context, idx[i]);
  2365.                  E_ToScreen(context, idx[i+1]);
  2366.                  E_ToScreen(context, idx[i+2]);
  2367.  
  2368.            if(context->CullFace_State == GL_FALSE)
  2369.            {
  2370.                visible = GL_TRUE;
  2371.            }
  2372.            else
  2373.            {
  2374.                      visible = E_CheckTri(context, &context->VertexBuffer[idx[i]], &context->VertexBuffer[idx[i+1]], &context->VertexBuffer[idx[i+2]], sign);
  2375.            }
  2376.  
  2377.                  if(visible)
  2378.                 {
  2379.            trichain[chainverts+0] = idx[i+0];
  2380.            trichain[chainverts+1] = idx[i+1];
  2381.            trichain[chainverts+2] = idx[i+2];
  2382.            chainverts += 3;
  2383.            }
  2384.             }
  2385.             else
  2386.             {
  2387.                if(context->CullFace_State == GL_FALSE || (local_or & MGL_CLIP_NEGW))
  2388.                {
  2389.              visible = GL_TRUE;
  2390.                  }
  2391.            else
  2392.                {
  2393.             visible = DecideFrontface(context, &(context->VertexBuffer[idx[i]]), &(context->VertexBuffer[idx[i+1]]), &(context->VertexBuffer[idx[i+2]]), sign);
  2394.                }
  2395.  
  2396.                if(visible)
  2397.                {
  2398.                    Convert(context, idx[i]);
  2399.                    Convert(context, idx[i+1]);
  2400.                    Convert(context, idx[i+2]);
  2401.  
  2402.                    clip[cnum].numverts = 3;
  2403.                    clip[cnum].verts[0] = idx[i];
  2404.                    clip[cnum].verts[1] = idx[i+1];
  2405.                    clip[cnum].verts[2] = idx[i+2];
  2406.  
  2407.                    AE_ClipPoly(context, &clip[cnum], free, local_or);
  2408.  
  2409.                    if(clip[cnum].numverts)
  2410.                    {
  2411.             free = clip[cnum].nextfree;
  2412.             cnum++;
  2413.                    }
  2414.                }
  2415.             }
  2416.         i+=3;
  2417.         }
  2418.     } while (i < count);
  2419.  
  2420.  
  2421.     if(chainverts)
  2422.     {
  2423.         error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIANGLES, W3D_INDEX_ULONG, chainverts, (void*)&trichain[0]);
  2424.     }
  2425.  
  2426.  
  2427.       if (cnum)
  2428.     {
  2429.     static PolyBuffer *p;
  2430.     static int start;
  2431.  
  2432.     if(verts == NULL)
  2433.     {
  2434.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  2435.                   if (!verts) return;
  2436.     }
  2437.  
  2438.     for(i=context->VertexBufferPointer; i<free; i++)
  2439.     {
  2440.         V_ToScreen(context, i);
  2441.     } 
  2442.  
  2443.     fan.st_pattern = NULL;
  2444.     fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2445.  
  2446.     start = 0;
  2447.     i = 0;
  2448.  
  2449.         do
  2450.         {
  2451.            p = &clip[i];
  2452.            j = 0;
  2453.  
  2454.            while (j < p->numverts)
  2455.            {
  2456.             int vert = p->verts[j];
  2457.             verts[start+j] = &(context->VertexBuffer[vert].v);
  2458.  
  2459.             if(vert < context->VertexBufferPointer)
  2460.             {
  2461.                 V_ToScreen(context, vert);
  2462.             }
  2463.            j++;
  2464.            }
  2465.  
  2466.         fan.v = &verts[start];
  2467.         fan.vertexcount = p->numverts;
  2468.  
  2469.         start += p->numverts;
  2470.  
  2471.         error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2472.  
  2473.         i++;
  2474.         } while (i < cnum);
  2475.       }
  2476. }
  2477.  
  2478. void E_DrawPolygon(GLcontext context, const int count, UWORD *idx)
  2479. {
  2480.     int i,j;
  2481.     ULONG error;
  2482.     ULONG and_code, or_code;
  2483.     PolyBuffer pclip;
  2484.       static W3D_Vertex **verts = NULL;
  2485.       static W3D_TrianglesV fan;
  2486.  
  2487.     if(Clip_Volume_Bypass != GL_FALSE)
  2488.     {
  2489.        int size = count;
  2490.  
  2491.        //first check if we are in guardband-mode
  2492.        //and discard offscreen primitives
  2493.  
  2494.        if((Clip_Volume_Bypass > GL_TRUE) && context->VertexBuffer[idx[0]].outcode)
  2495.        {
  2496.         ULONG local_and;
  2497.  
  2498.         i = size - 2;
  2499.  
  2500.         local_and = context->VertexBuffer[idx[0]].outcode & context->VertexBuffer[idx[i]].outcode & context->VertexBuffer[idx[i+1]].outcode;
  2501.  
  2502.         if(local_and)
  2503.         {
  2504.             i--;
  2505.  
  2506.             while (i)
  2507.             {
  2508.                if((local_and & context->VertexBuffer[idx[i]].outcode) == 0)
  2509.                 break;
  2510.                i--;
  2511.             }
  2512.         }
  2513.  
  2514.         if(i == 0)
  2515.         return;
  2516.  
  2517.         size = i+2;
  2518.        }
  2519.  
  2520.        if(context->CullFace_State == GL_TRUE)
  2521.        {
  2522.         float x0,y0;
  2523.         float x1,y1;
  2524.         float x2,y2;
  2525.         GLfloat area;
  2526.  
  2527.         #define x(a) (context->VertexBuffer[idx[a]].v.x)
  2528.         #define y(a) (context->VertexBuffer[idx[a]].v.y)
  2529.  
  2530.         x0 = x(0);
  2531.         y0 = y(0);
  2532.         x1 = x(1) - x0;
  2533.         y1 = y(1) - y0;
  2534.         x2 = x(2) - x0;
  2535.         y2 = y(2) - y0;
  2536.  
  2537.         area = y2*x1 - x2*y1;
  2538.  
  2539.         i = 1;
  2540.  
  2541.         while (i < size-2)
  2542.         {
  2543.            x1 = x2;
  2544.            y1 = y2;
  2545.            x2 = x(i+2) - x0;
  2546.            y2 = y(i+2) - y0;
  2547.  
  2548.            area += y2*x1 - x2*y1;
  2549.            i++;
  2550.         }        
  2551.  
  2552.         if(context->CurrentCullSign > 0)
  2553.         area = -area;
  2554.  
  2555.         if(area < context->MinTriArea)
  2556.         return;
  2557.  
  2558.         #undef x
  2559.         #undef y
  2560.        }
  2561.  
  2562.        error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, size, (void *)idx);
  2563.  
  2564.     return;
  2565.     }
  2566.  
  2567.     if(context->ArrayPointer.transformed == GL_FALSE)
  2568.     {
  2569.         TransformIndex(context, count, idx);
  2570.     }
  2571.  
  2572.     or_code = 0;
  2573.     and_code = 0xff;
  2574.  
  2575.     for(i=0; i<count; i++)
  2576.     {
  2577.         and_code &= context->VertexBuffer[idx[i]].outcode;
  2578.         or_code |= context->VertexBuffer[idx[i]].outcode;
  2579.     }
  2580.  
  2581.     if(and_code)
  2582.         return;
  2583.  
  2584.     if (or_code == 0)
  2585.     {
  2586.        if(context->ArrayPointer.transformed == GL_FALSE)
  2587.        {
  2588.         E_ToScreenArray(context, count, idx);
  2589.        }
  2590.  
  2591.        if(context->CullFace_State == GL_TRUE)
  2592.        {
  2593.         float x0,y0;
  2594.         float x1,y1;
  2595.         float x2,y2;
  2596.         GLfloat area;
  2597.  
  2598.         #define x(a) (context->VertexBuffer[idx[a]].v.x)
  2599.         #define y(a) (context->VertexBuffer[idx[a]].v.y)
  2600.  
  2601.         x0 = x(0);
  2602.         y0 = y(0);
  2603.         x1 = x(1) - x0;
  2604.         y1 = y(1) - y0;
  2605.         x2 = x(2) - x0;
  2606.         y2 = y(2) - y0;
  2607.  
  2608.         area = y2*x1 - x2*y1;
  2609.  
  2610.         i = 1;
  2611.  
  2612.         while (i < count-2 && fabs(area) < context->MinTriArea)
  2613.         {
  2614.            x1 = x2;
  2615.            y1 = y2;
  2616.            x2 = x(i+2) - x0;
  2617.            y2 = y(i+2) - y0;
  2618.  
  2619.            area += y2*x1 - x2*y1;
  2620.            i++;
  2621.         }        
  2622.  
  2623.         if(context->CurrentCullSign > 0)
  2624.         area = -area;
  2625.  
  2626.         if(area < context->MinTriArea)
  2627.         return;
  2628.  
  2629.         #undef x
  2630.         #undef y
  2631.        }
  2632.  
  2633.     error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, count, (void *)idx);
  2634.  
  2635.     return;
  2636.     }
  2637.  
  2638.     if(verts == NULL)
  2639.     {
  2640.             verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  2641.                   if (!verts) return;
  2642.     }
  2643.  
  2644.     i = 0;
  2645.     do
  2646.     {
  2647.         Convert(context, idx[i]);
  2648.         pclip.verts[i] = idx[i];
  2649.  
  2650.     i++;
  2651.     } while (i < count);
  2652.  
  2653.     pclip.numverts = count;
  2654.  
  2655.     AE_ClipPoly(context, &pclip, context->VertexBufferPointer, or_code);
  2656.  
  2657.     if(pclip.numverts < 3)
  2658.         return;
  2659.  
  2660.     for(i=context->VertexBufferPointer; i<pclip.nextfree; i++)
  2661.     {
  2662.         V_ToScreen(context, i);
  2663.     }
  2664.  
  2665.     if(context->ArrayPointer.transformed == GL_FALSE)
  2666.     {
  2667.        int vert;
  2668.  
  2669.        i = 0;
  2670.        do           
  2671.        {
  2672.         vert = pclip.verts[i];
  2673.  
  2674.         if(vert > context->VertexBufferPointer)
  2675.         V_ToScreen(context, vert);
  2676.  
  2677.         verts[i] = &(context->VertexBuffer[vert].v);
  2678.  
  2679.        i++;
  2680.        } while (i < pclip.numverts);
  2681.     }
  2682.     else
  2683.     {
  2684.        i = 0;
  2685.        do           
  2686.        {
  2687.         verts[i] = &(context->VertexBuffer[pclip.verts[i]].v);
  2688.  
  2689.        i++;
  2690.        } while (i < pclip.numverts);
  2691.     }
  2692.  
  2693.     if(context->CullFace_State == GL_TRUE)
  2694.     {
  2695.         float x0,y0;
  2696.         float x1,y1;
  2697.         float x2,y2;
  2698.         GLfloat area;
  2699.  
  2700.         #define x(a) (context->VertexBuffer[pclip.verts[a]].v.x)
  2701.         #define y(a) (context->VertexBuffer[pclip.verts[a]].v.y)
  2702.  
  2703.         x0 = x(0);
  2704.         y0 = y(0);
  2705.         x1 = x(1) - x0;
  2706.         y1 = y(1) - y0;
  2707.         x2 = x(2) - x0;
  2708.         y2 = y(2) - y0;
  2709.  
  2710.         area = y2*x1 - x2*y1;
  2711.  
  2712.         i = 1;
  2713.  
  2714.         while (i < pclip.numverts-2 && fabs(area) < context->MinTriArea)
  2715.         {
  2716.            x1 = x2;
  2717.            y1 = y2;
  2718.            x2 = x(i+2) - x0;
  2719.            y2 = y(i+2) - y0;
  2720.  
  2721.            area += y2*x1 - x2*y1;
  2722.            i++;
  2723.         }        
  2724.  
  2725.         if(context->CurrentCullSign > 0)
  2726.         area = -area;
  2727.  
  2728.         if(area < context->MinTriArea)
  2729.         return;
  2730.  
  2731.         #undef x
  2732.         #undef y
  2733.     }
  2734.  
  2735.  
  2736.     fan.tex = context->w3dTexBuffer[context->CurrentBinding];
  2737.     fan.st_pattern = NULL;
  2738.     fan.v = verts;
  2739.     fan.vertexcount = pclip.numverts;
  2740.  
  2741.     error = W3D_DrawTriFanV(context->w3dContext, &fan);
  2742. }
  2743.  
  2744. void E_DrawFlatFan(GLcontext context, const int count, const UWORD *idx)
  2745. {
  2746.     int i;
  2747.     int vnum;
  2748.     ULONG error;
  2749.     int Vstride;
  2750.     int Wstride;
  2751.       float *W;
  2752.       float *V;
  2753.      MGLVertex *v;
  2754.  
  2755.       Vstride = context->ArrayPointer.vertexstride;
  2756.       Wstride = context->ArrayPointer.texcoordstride;
  2757.  
  2758.      i = 0;
  2759.     do
  2760.     {
  2761.     vnum = idx[i];
  2762.  
  2763.       v = &context->VertexBuffer[vnum];
  2764.     V = (float*)(context->ArrayPointer.verts + vnum * Vstride);
  2765.  
  2766.          v->v.x = V[0];
  2767.          v->v.y = V[1];
  2768.          v->v.z = (double)V[2];
  2769.  
  2770.          if(context->ClientState & GLCS_TEXTURE)
  2771.          {
  2772.         W = (float*)((UBYTE*)context->WBuffer + vnum * Wstride);
  2773.               *W = 1.0;
  2774.          }
  2775.  
  2776.     i++;
  2777.       } while (i < count);
  2778.  
  2779.    error = W3D_DrawElements(context->w3dContext, W3D_PRIMITIVE_TRIFAN, W3D_INDEX_UWORD, count, (void *)idx);
  2780. }
  2781.  
  2782. //Range guardband-check added 18-05-02 (surgeon)
  2783.  
  2784. INLINE ULONG TestRangeGuardBand(GLcontext context, GLuint first, GLsizei count)
  2785. {
  2786.     int i; 
  2787.     ULONG border;
  2788.     MGLVertex *v;
  2789.  
  2790.     v = &context->VertexBuffer[first];
  2791.  
  2792.     i = 0;
  2793.     border = 0;
  2794.  
  2795.     while (i < count && border == 0)
  2796.     {
  2797.        if(v->outcode)
  2798.        {
  2799.         float gcw = v->bw * 2.0;
  2800.  
  2801.         if (-gcw > v->bx)
  2802.             border |= MGL_CLIP_LEFT;
  2803.         else if (v->bx > gcw)
  2804.             border |= MGL_CLIP_RIGHT;
  2805.         if (-gcw > v->by)
  2806.             border |= MGL_CLIP_BOTTOM;
  2807.         else if (v->by > gcw)
  2808.             border |= MGL_CLIP_TOP;
  2809.        }
  2810.  
  2811.        i++;
  2812.        v++;
  2813.     }
  2814.  
  2815.     return border;
  2816. }
  2817.  
  2818. //FIXME: avoid redundary projections to a greater extent based on some simple statistics (on/off screen verts).
  2819.  
  2820. void GLLockArrays(GLcontext context, GLuint first, GLsizei count)
  2821. {
  2822.     int check_outcodes;
  2823.     ULONG offscreen;
  2824.  
  2825.     //pre-transform and code all verts within range:
  2826.  
  2827.     context->ArrayPointer.transformed = GL_TRUE;
  2828.     context->ArrayPointer.lockfirst = first;
  2829.     context->ArrayPointer.locksize  = count;
  2830.  
  2831.     offscreen = TransformRange(context, first, count);
  2832.  
  2833.     //extra test added 18-05-02:
  2834.     if(offscreen && !(offscreen & context->ClipFlags))
  2835.     {
  2836.         check_outcodes = 1;
  2837.  
  2838.         offscreen = TestRangeGuardBand(context, first, count);
  2839.     }
  2840.     else
  2841.     {
  2842.         check_outcodes = 0;
  2843.     }
  2844.  
  2845.     //project verts:
  2846.  
  2847.     if (offscreen)
  2848.     {
  2849.         Clip_Volume_Bypass = GL_FALSE;
  2850.  
  2851.         //handles fix2float if needed:
  2852.  
  2853.         ProjectRangeByOutcode(context, first, count);
  2854.  
  2855.  
  2856.     context->w3dContext->VPMode = W3D_VERTEX_F_F_D;
  2857.     context->w3dContext->VertexPointer = (void *)&(context->VertexBuffer[0].v.x);
  2858.     }
  2859.     else //all vertices on screen
  2860.     {
  2861.         Clip_Volume_Bypass = GL_TRUE + check_outcodes;
  2862.  
  2863.         ProjectRange(context, first, count);
  2864.  
  2865.     //we don't need to move w3d vertexpointer
  2866.      //because only the results of the projection
  2867.     //are used later on.
  2868.     //However, path needs to be seperated from standard
  2869.     //because of backface culling.
  2870.     }
  2871. }
  2872.  
  2873. void GLUnlockArrays(GLcontext context)
  2874. {
  2875.     context->ArrayPointer.transformed = GL_FALSE;
  2876.     context->ArrayPointer.lockfirst = 0;
  2877.     context->ArrayPointer.locksize = 0;
  2878.  
  2879.     if(Clip_Volume_Bypass == GL_FALSE)
  2880.     {
  2881.     context->w3dContext->VPMode = W3D_VERTEX_F_F_F;
  2882.     context->w3dContext->VertexPointer = (void *)&(context->VertexBuffer[0].bx);
  2883.     }
  2884.  
  2885.     Clip_Volume_Bypass = GL_FALSE;
  2886. }
  2887.  
  2888. static INLINE void PreDraw(GLcontext context)
  2889. {
  2890.    if (context->FogDirty && context->Fog_State)
  2891.    {
  2892.         fog_Set(context);
  2893.         context->FogDirty = GL_FALSE;
  2894.    }
  2895.  
  2896.    if (context->ShadeModel == GL_FLAT && context->UpdateCurrentColor == GL_TRUE)
  2897.    {
  2898.     context->UpdateCurrentColor = GL_FALSE;
  2899.     W3D_SetCurrentColor(context->w3dContext, &context->CurrentColor);
  2900.    }
  2901.  
  2902. #ifdef AUTOMATIC_LOCKING_ENABLE
  2903.  
  2904.    if (context->LockMode == MGL_LOCK_MANUAL)
  2905.         return;
  2906.  
  2907.    else if (context->LockMode == MGL_LOCK_AUTOMATIC) // Automatic: Lock per primitive
  2908.    {
  2909.         if (W3D_SUCCESS == W3D_LockHardware(context->w3dContext))
  2910.         {
  2911.                 context->w3dLocked = GL_TRUE;
  2912.         }
  2913.         else
  2914.         {
  2915.                 printf("Error during LockHardware\n");
  2916.         }
  2917.    }
  2918.    else // Smart: Lock timer based
  2919.    {
  2920.         if (context->w3dLocked == GL_FALSE)
  2921.         {
  2922.             if (W3D_SUCCESS != W3D_LockHardware(context->w3dContext))
  2923.             {
  2924.                 return; // give up
  2925.             }
  2926.             context->w3dLocked = GL_TRUE;
  2927.             TMA_Start(&(context->LockTime));
  2928.         }
  2929.    }
  2930.  
  2931. #endif
  2932.  
  2933. }
  2934.  
  2935. static INLINE void PostDraw(GLcontext context)
  2936. {
  2937.     context->VertexBufferPointer = 0;
  2938.  
  2939. #ifdef AUTOMATIC_LOCKING_ENABLE
  2940.  
  2941.     if (context->LockMode == MGL_LOCK_SMART && TMA_Check(&(context->LockTime)) == GL_TRUE)
  2942.     {
  2943.         // Time to unlock
  2944.         W3D_UnLockHardware(context->w3dContext);
  2945.         context->w3dLocked = GL_FALSE;
  2946.     }
  2947.     else if (context->LockMode == MGL_LOCK_AUTOMATIC)
  2948.     {
  2949.          W3D_UnLockHardware(context->w3dContext);
  2950.          context->w3dLocked = GL_FALSE;
  2951.     }
  2952.  
  2953. #endif
  2954.  
  2955. }
  2956.  
  2957.  
  2958. void GLDrawElements(GLcontext context, GLenum mode, const GLsizei count, GLenum type, const GLvoid *indices)
  2959. {
  2960.    int i;
  2961.    ULONG error, prim;
  2962.    UBYTE *ub;
  2963.    ULONG *ul;
  2964.    UWORD *idx;
  2965.  
  2966. #ifdef VA_SANITY_CHECK
  2967.    GLboolean ShadeModel_bypass;
  2968.    GLboolean TexCoord_bypass;
  2969. #endif
  2970.  
  2971.    switch(type)
  2972.    {
  2973.       case GL_UNSIGNED_SHORT:
  2974.             idx = (UWORD*)indices;
  2975.  
  2976.     break;
  2977.  
  2978.       case GL_UNSIGNED_BYTE:
  2979.  
  2980.         ub = (UBYTE *)indices;
  2981.         idx = context->ElementIndex;
  2982.  
  2983.         idx[0] = ub[0];
  2984.         idx[1] = ub[1];
  2985.         idx[2] = ub[2];
  2986.  
  2987.         i = 3;
  2988.  
  2989.         while (i < count)
  2990.         {
  2991.             idx[i] = ub[i];
  2992.         i++;
  2993.         }
  2994.     break;
  2995.  
  2996.       case GL_UNSIGNED_INT:
  2997.  
  2998.         ul = (ULONG *)indices;
  2999.         idx = context->ElementIndex;
  3000.  
  3001.         idx[0] = ul[0];
  3002.         idx[1] = ul[1];
  3003.         idx[2] = ul[2];
  3004.  
  3005.         i = 3;
  3006.  
  3007.         while (i < count)
  3008.         {
  3009.             idx[i] = ul[i];
  3010.         i++;
  3011.         }
  3012.  
  3013.     break;
  3014.  
  3015.       default:
  3016.  
  3017.         GLFlagError(context, 1, GL_INVALID_ENUM);
  3018.  
  3019.     break;
  3020.    }
  3021.  
  3022. #ifdef VA_SANITY_CHECK
  3023.  
  3024.    ShadeModel_bypass = GL_FALSE;
  3025.  
  3026.    if(context->ShadeModel == GL_SMOOTH && !(context->ClientState & GLCS_COLOR))
  3027.    {
  3028.     W3D_SetState(context->w3dContext, W3D_GOURAUD, W3D_DISABLE);
  3029.     context->ShadeModel = GL_FLAT;
  3030.        ShadeModel_bypass = GL_TRUE;
  3031.    }
  3032.  
  3033. #endif
  3034.  
  3035.    PreDraw(context);
  3036.  
  3037. #ifdef VA_SANITY_CHECK
  3038.  
  3039.    TexCoord_bypass = GL_FALSE;
  3040.  
  3041.    if(context->Texture2D_State[0] == GL_FALSE || !(context->ClientState & GLCS_TEXTURE))
  3042.    {
  3043.       Set_W3D_Texture(context->w3dContext, 0, NULL);
  3044.  
  3045.     if(context->ClientState & GLCS_TEXTURE)
  3046.     {
  3047.        context->ClientState &= ~GLCS_TEXTURE;
  3048.        TexCoord_bypass = GL_TRUE;
  3049.     }
  3050.    }
  3051.  
  3052. #else
  3053.  
  3054.    if(context->Texture2D_State[0] == GL_FALSE)
  3055.    {
  3056.       Set_W3D_Texture(context->w3dContext, 0, NULL);
  3057.    }
  3058.  
  3059. #endif
  3060.  
  3061.    else
  3062.    {
  3063.         Set_W3D_Texture(context->w3dContext, 0, context->w3dTexBuffer[context->CurrentBinding]);
  3064.    }
  3065.  
  3066.  
  3067.    if(context->VertexArrayPipeline == GL_FALSE)
  3068.    {
  3069.     switch(mode)
  3070.     {
  3071.         case GL_POINTS:
  3072.         prim = W3D_PRIMITIVE_POINTS;
  3073.         break;
  3074.         case GL_LINE_STRIP:
  3075.         prim = W3D_PRIMITIVE_LINESTRIP;
  3076.         break;
  3077.         case GL_LINE_LOOP:
  3078.         prim = W3D_PRIMITIVE_LINELOOP;
  3079.         break;
  3080.         case GL_LINES:
  3081.         prim = W3D_PRIMITIVE_LINES;
  3082.         break;
  3083.         case GL_TRIANGLE_STRIP:
  3084.         prim = W3D_PRIMITIVE_TRISTRIP;
  3085.         break;
  3086.         case MGL_FLATFAN:
  3087.       case GL_POLYGON:
  3088.         case GL_TRIANGLE_FAN:
  3089.          prim = W3D_PRIMITIVE_TRIFAN;
  3090.         break;
  3091.         case GL_TRIANGLES:
  3092.         prim = W3D_PRIMITIVE_TRIANGLES;
  3093.         break;
  3094.         default:
  3095.             GLFlagError(context, 1, GL_INVALID_ENUM);
  3096.     }
  3097.  
  3098.     error = W3D_DrawElements(context->w3dContext, prim, W3D_INDEX_UWORD, count, (void*)&idx[0]);
  3099.    }
  3100.    else
  3101.    {
  3102.  
  3103.     if(context->ArrayPointer.transformed == GL_FALSE)
  3104.     {
  3105.     context->w3dContext->VPMode = W3D_VERTEX_F_F_D;
  3106.     context->w3dContext->VertexPointer = (void *)&(context->VertexBuffer[0].v.x);
  3107.  
  3108.     context->VertexBufferPointer = context->VertexBufferSize / 2;
  3109.     //avoid index-scan. Is this margin a safe assumption ?
  3110.     }
  3111.     else
  3112.     {
  3113.     context->VertexBufferPointer = context->ArrayPointer.lockfirst + context->ArrayPointer.locksize;
  3114.     }
  3115.  
  3116. #if 0
  3117.     if((count == 3) && (mode != MGL_FLATFAN))
  3118.     {
  3119.         E_DrawTriangle(context, idx);
  3120.     }
  3121.     else
  3122. #endif
  3123.     switch(mode)
  3124.     {
  3125.         case GL_TRIANGLE_STRIP:
  3126.         E_DrawTriStrip(context, count, idx);
  3127.         break;
  3128.  
  3129.         case GL_TRIANGLE_FAN:
  3130.         E_DrawTriFan(context, count, idx);
  3131.         break;
  3132.  
  3133.         case GL_TRIANGLES:
  3134.         E_DrawTriangles(context, count, idx);
  3135.         break;
  3136.  
  3137.         case GL_POLYGON:
  3138.         E_DrawPolygon(context, count, idx);
  3139.         break;
  3140.  
  3141.         case MGL_FLATFAN:
  3142.         E_DrawFlatFan(context, count, idx);
  3143.         break;
  3144.  
  3145.         default:
  3146.         GLFlagError(context, 1, GL_INVALID_ENUM);
  3147.     }
  3148.  
  3149.     if(context->ArrayPointer.transformed == GL_FALSE)
  3150.     {
  3151.     context->w3dContext->VPMode = W3D_VERTEX_F_F_F;
  3152.     context->w3dContext->VertexPointer = (void *)&(context->VertexBuffer[0].bx);
  3153.     }
  3154.    }
  3155.  
  3156.    PostDraw(context);
  3157.  
  3158. #ifdef VA_SANITY_CHECK
  3159.  
  3160.    if(ShadeModel_bypass == GL_TRUE)
  3161.    {
  3162.     W3D_SetState(context->w3dContext, W3D_GOURAUD, W3D_ENABLE);
  3163.     context->ShadeModel = GL_SMOOTH;
  3164.    }
  3165.  
  3166.    if(TexCoord_bypass == GL_TRUE)
  3167.    {
  3168.     context->ClientState |= GLCS_TEXTURE;
  3169.    }
  3170.  
  3171. #endif
  3172.  
  3173. }
  3174.  
  3175. #ifdef __VBCC__
  3176. #undef V_ToScreen
  3177. #endif
  3178.